Vite build tools #695
@ -1,7 +1,15 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
plugins: ["@typescript-eslint"],
|
plugins: ["@typescript-eslint", "formatjs"],
|
||||||
|
rules: {
|
||||||
|
"formatjs/enforce-id": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"idInterpolationPattern": "[sha512:contenthash:base64:6]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
root: true,
|
root: true,
|
||||||
ignorePatterns: ["build/", "*.test.ts", "*.js"],
|
ignorePatterns: ["build/", "*.test.ts", "*.js"],
|
||||||
env: {
|
env: {
|
||||||
|
@ -5,15 +5,14 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="Feature packed nostr client" />
|
<meta name="description" content="Feature packed nostr client" />
|
||||||
<meta
|
<meta name="keywords" content="nostr snort fast decentralized social media censorship resistant open source software" />
|
||||||
name="keywords"
|
|
||||||
content="nostr snort fast decentralized social media censorship resistant open source software" />
|
|
||||||
<link rel="preconnect" href="https://imgproxy.snort.social" />
|
<link rel="preconnect" href="https://imgproxy.snort.social" />
|
||||||
<link rel="apple-touch-icon" href="<%= htmlWebpackPlugin.options.templateParameters.appleTouchIconUrl %>" />
|
<link rel="apple-touch-icon" href="" />
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<title><%= htmlWebpackPlugin.options.templateParameters.appTitle %></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -48,8 +48,9 @@
|
|||||||
"workbox-strategies": "^6.4.2"
|
"workbox-strategies": "^6.4.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack serve --node-env=development --mode=development",
|
"start": "vite",
|
||||||
"build": "webpack --node-env=production --mode=production",
|
"build": "yarn eslint --fix && vite build",
|
||||||
|
"serve": "vite preview",
|
||||||
"test": "jest --runInBand",
|
"test": "jest --runInBand",
|
||||||
"intl-extract": "formatjs extract 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file src/lang.json --flatten true",
|
"intl-extract": "formatjs extract 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file src/lang.json --flatten true",
|
||||||
"intl-compile": "formatjs compile src/lang.json --out-file src/translations/en.json",
|
"intl-compile": "formatjs compile src/lang.json --out-file src/translations/en.json",
|
||||||
@ -83,6 +84,7 @@
|
|||||||
"@formatjs/cli": "^6.1.3",
|
"@formatjs/cli": "^6.1.3",
|
||||||
"@formatjs/ts-transformer": "^3.13.3",
|
"@formatjs/ts-transformer": "^3.13.3",
|
||||||
"@jest/globals": "^29.6.1",
|
"@jest/globals": "^29.6.1",
|
||||||
|
"@types/config": "^3.3.3",
|
||||||
"@types/debug": "^4.1.8",
|
"@types/debug": "^4.1.8",
|
||||||
"@types/jest": "^29.5.1",
|
"@types/jest": "^29.5.1",
|
||||||
"@types/node": "^20.4.1",
|
"@types/node": "^20.4.1",
|
||||||
@ -94,6 +96,7 @@
|
|||||||
"@types/webtorrent": "^0.109.3",
|
"@types/webtorrent": "^0.109.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
||||||
"@typescript-eslint/parser": "^6.1.0",
|
"@typescript-eslint/parser": "^6.1.0",
|
||||||
|
"@vitejs/plugin-react": "^4.2.0",
|
||||||
"@webbtc/webln-types": "^1.0.10",
|
"@webbtc/webln-types": "^1.0.10",
|
||||||
"@webpack-cli/generators": "^3.0.4",
|
"@webpack-cli/generators": "^3.0.4",
|
||||||
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
|
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
|
||||||
@ -104,6 +107,7 @@
|
|||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"css-minimizer-webpack-plugin": "^5.0.0",
|
"css-minimizer-webpack-plugin": "^5.0.0",
|
||||||
"eslint": "^8.48.0",
|
"eslint": "^8.48.0",
|
||||||
|
"eslint-plugin-formatjs": "^4.11.3",
|
||||||
"eslint-webpack-plugin": "^4.0.1",
|
"eslint-webpack-plugin": "^4.0.1",
|
||||||
"html-webpack-plugin": "^5.5.1",
|
"html-webpack-plugin": "^5.5.1",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
@ -114,6 +118,7 @@
|
|||||||
"postcss-preset-env": "^9.2.0",
|
"postcss-preset-env": "^9.2.0",
|
||||||
"prettier": "2.8.3",
|
"prettier": "2.8.3",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
|
"rollup-plugin-visualizer": "^5.9.2",
|
||||||
"source-map-loader": "^4.0.1",
|
"source-map-loader": "^4.0.1",
|
||||||
"tailwindcss": "^3.3.3",
|
"tailwindcss": "^3.3.3",
|
||||||
"terser-webpack-plugin": "^5.3.9",
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
@ -121,6 +126,8 @@
|
|||||||
"ts-jest": "^29.1.1",
|
"ts-jest": "^29.1.1",
|
||||||
"ts-loader": "^9.4.4",
|
"ts-loader": "^9.4.4",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.0.0",
|
||||||
|
"vite-plugin-pwa": "^0.17.0",
|
||||||
"webpack": "^5.88.2",
|
"webpack": "^5.88.2",
|
||||||
"webpack-bundle-analyzer": "^4.8.0",
|
"webpack-bundle-analyzer": "^4.8.0",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { NostrEvent } from "@snort/system";
|
import { NostrEvent } from "@snort/system";
|
||||||
import { FeedCache } from "@snort/shared";
|
import { FeedCache } from "@snort/shared";
|
||||||
import { db } from "Db";
|
import { db } from "@/Db";
|
||||||
|
|
||||||
export class ChatCache extends FeedCache<NostrEvent> {
|
export class ChatCache extends FeedCache<NostrEvent> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FeedCache } from "@snort/shared";
|
import { FeedCache } from "@snort/shared";
|
||||||
import { db, EventInteraction } from "Db";
|
import { db, EventInteraction } from "@/Db";
|
||||||
import { LoginStore } from "Login";
|
import { LoginStore } from "@/Login";
|
||||||
import { sha256 } from "SnortUtils";
|
import { sha256 } from "@/SnortUtils";
|
||||||
|
|
||||||
export class EventInteractionCache extends FeedCache<EventInteraction> {
|
export class EventInteractionCache extends FeedCache<EventInteraction> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { db } from "Db";
|
import { db } from "@/Db";
|
||||||
import { unixNowMs } from "@snort/shared";
|
import { unixNowMs } from "@snort/shared";
|
||||||
import { EventKind, RequestBuilder, socialGraphInstance, TaggedNostrEvent } from "@snort/system";
|
import { EventKind, RequestBuilder, socialGraphInstance, TaggedNostrEvent } from "@snort/system";
|
||||||
import { RefreshFeedCache } from "./RefreshFeedCache";
|
import { RefreshFeedCache } from "./RefreshFeedCache";
|
||||||
import { LoginSession } from "Login";
|
import { LoginSession } from "@/Login";
|
||||||
|
|
||||||
export class FollowListCache extends RefreshFeedCache<TaggedNostrEvent> {
|
export class FollowListCache extends RefreshFeedCache<TaggedNostrEvent> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -2,10 +2,10 @@ import debug from "debug";
|
|||||||
import { EventKind, RequestBuilder, SystemInterface, TaggedNostrEvent } from "@snort/system";
|
import { EventKind, RequestBuilder, SystemInterface, TaggedNostrEvent } from "@snort/system";
|
||||||
import { unixNow, unixNowMs } from "@snort/shared";
|
import { unixNow, unixNowMs } from "@snort/shared";
|
||||||
|
|
||||||
import { db } from "Db";
|
import { db } from "@/Db";
|
||||||
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
|
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
|
||||||
import { LoginSession } from "Login";
|
import { LoginSession } from "@/Login";
|
||||||
import { Day, Hour } from "Const";
|
import { Day, Hour } from "@/Const";
|
||||||
|
|
||||||
const WindowSize = Hour * 6;
|
const WindowSize = Hour * 6;
|
||||||
const MaxCacheWindow = Day * 7;
|
const MaxCacheWindow = Day * 7;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { EventKind, EventPublisher, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
import { EventKind, EventPublisher, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||||
import { UnwrappedGift, db } from "Db";
|
import { UnwrappedGift, db } from "@/Db";
|
||||||
import { findTag, unwrap } from "SnortUtils";
|
import { findTag, unwrap } from "@/SnortUtils";
|
||||||
import { RefreshFeedCache } from "./RefreshFeedCache";
|
import { RefreshFeedCache } from "./RefreshFeedCache";
|
||||||
import { LoginSession, LoginSessionType } from "Login";
|
import { LoginSession, LoginSessionType } from "@/Login";
|
||||||
|
|
||||||
export class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {
|
export class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { EventKind, NostrEvent, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
import { EventKind, NostrEvent, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||||
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
|
import { RefreshFeedCache, TWithCreated } from "./RefreshFeedCache";
|
||||||
import { LoginSession } from "Login";
|
import { LoginSession } from "@/Login";
|
||||||
import { NostrEventForSession, db } from "Db";
|
import { NostrEventForSession, db } from "@/Db";
|
||||||
import { Day } from "Const";
|
import { Day } from "@/Const";
|
||||||
import { unixNow } from "@snort/shared";
|
import { unixNow } from "@snort/shared";
|
||||||
|
|
||||||
export class NotificationsCache extends RefreshFeedCache<NostrEventForSession> {
|
export class NotificationsCache extends RefreshFeedCache<NostrEventForSession> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Payment, db } from "Db";
|
import { Payment, db } from "@/Db";
|
||||||
import { FeedCache } from "@snort/shared";
|
import { FeedCache } from "@snort/shared";
|
||||||
|
|
||||||
export class Payments extends FeedCache<Payment> {
|
export class Payments extends FeedCache<Payment> {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FeedCache } from "@snort/shared";
|
import { FeedCache } from "@snort/shared";
|
||||||
import { EventPublisher, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
import { EventPublisher, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||||
import { LoginSession } from "Login";
|
import { LoginSession } from "@/Login";
|
||||||
|
|
||||||
export type TWithCreated<T> = (T | Readonly<T>) & { created_at: number };
|
export type TWithCreated<T> = (T | Readonly<T>) & { created_at: number };
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "./AsyncButton.css";
|
import "./AsyncButton.css";
|
||||||
import React, { ForwardedRef } from "react";
|
import React, { ForwardedRef } from "react";
|
||||||
import Spinner from "../Icons/Spinner";
|
import Spinner from "../Icons/Spinner";
|
||||||
import useLoading from "Hooks/useLoading";
|
import useLoading from "@/Hooks/useLoading";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
export interface AsyncButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
export interface AsyncButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import useLoading from "Hooks/useLoading";
|
import useLoading from "@/Hooks/useLoading";
|
||||||
import Spinner from "Icons/Spinner";
|
import Spinner from "@/Icons/Spinner";
|
||||||
|
|
||||||
export type AsyncIconProps = React.HTMLProps<HTMLDivElement> & {
|
export type AsyncIconProps = React.HTMLProps<HTMLDivElement> & {
|
||||||
iconName: string;
|
iconName: string;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "./BackButton.css";
|
import "./BackButton.css";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { MetadataCache } from "@snort/system";
|
import { MetadataCache } from "@snort/system";
|
||||||
|
|
||||||
import { ChatParticipant } from "chat";
|
import { ChatParticipant } from "@/chat";
|
||||||
import NoteToSelf from "../User/NoteToSelf";
|
import NoteToSelf from "../User/NoteToSelf";
|
||||||
import ProfileImage from "../User/ProfileImage";
|
import ProfileImage from "../User/ProfileImage";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
|
||||||
export function ChatParticipantProfile({ participant }: { participant: ChatParticipant }) {
|
export function ChatParticipantProfile({ participant }: { participant: ChatParticipant }) {
|
||||||
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
||||||
|
@ -3,11 +3,11 @@ import { useEffect, useState } from "react";
|
|||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useInView } from "react-intersection-observer";
|
import { useInView } from "react-intersection-observer";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import NoteTime from "Element/Event/NoteTime";
|
import NoteTime from "@/Element/Event/NoteTime";
|
||||||
import Text from "Element/Text";
|
import Text from "@/Element/Text";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { Chat, ChatMessage, ChatType, setLastReadIn } from "chat";
|
import { Chat, ChatMessage, ChatType, setLastReadIn } from "@/chat";
|
||||||
import ProfileImage from "../User/ProfileImage";
|
import ProfileImage from "../User/ProfileImage";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
@ -61,7 +61,7 @@ export default function DM(props: DMProps) {
|
|||||||
{content ? (
|
{content ? (
|
||||||
<Text id={msg.id} content={content} tags={[]} creator={otherPubkey} />
|
<Text id={msg.id} content={content} tags={[]} creator={otherPubkey} />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage defaultMessage="Loading..." />
|
<FormattedMessage defaultMessage="Loading..." id="gjBiyj" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import "./DmWindow.css";
|
import "./DmWindow.css";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import DM from "Element/Chat/DM";
|
import DM from "@/Element/Chat/DM";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import WriteMessage from "Element/Chat/WriteMessage";
|
import WriteMessage from "@/Element/Chat/WriteMessage";
|
||||||
import { Chat, createEmptyChatObject, useChatSystem } from "chat";
|
import { Chat, createEmptyChatObject, useChatSystem } from "@/chat";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { ChatParticipantProfile } from "./ChatParticipant";
|
import { ChatParticipantProfile } from "./ChatParticipant";
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ export default function DmWindow({ id }: { id: string }) {
|
|||||||
{chat.participants.map(v => (
|
{chat.participants.map(v => (
|
||||||
<ProfileImage pubkey={v.id} showUsername={false} />
|
<ProfileImage pubkey={v.id} showUsername={false} />
|
||||||
))}
|
))}
|
||||||
{chat.title ?? <FormattedMessage defaultMessage="Secret Group Chat" />}
|
{chat.title ?? <FormattedMessage defaultMessage="Secret Group Chat" id="+Vxixo" />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { NostrEvent, NostrLink, NostrPrefix } from "@snort/system";
|
import { NostrEvent, NostrLink, NostrPrefix } from "@snort/system";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "@/Upload";
|
||||||
import { openFile } from "SnortUtils";
|
import { openFile } from "@/SnortUtils";
|
||||||
import Textarea from "../Textarea";
|
import Textarea from "../Textarea";
|
||||||
import { Chat } from "chat";
|
import { Chat } from "@/chat";
|
||||||
import { AsyncIcon } from "Element/AsyncIcon";
|
import { AsyncIcon } from "@/Element/AsyncIcon";
|
||||||
|
|
||||||
export default function WriteMessage({ chat }: { chat: Chat }) {
|
export default function WriteMessage({ chat }: { chat: Chat }) {
|
||||||
const [msg, setMsg] = useState("");
|
const [msg, setMsg] = useState("");
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useState, ReactNode } from "react";
|
import { useState, ReactNode } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import ShowMore from "Element/Event/ShowMore";
|
import ShowMore from "@/Element/Event/ShowMore";
|
||||||
|
|
||||||
interface CollapsedProps {
|
interface CollapsedProps {
|
||||||
text?: string;
|
text?: string;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "./Copy.css";
|
import "./Copy.css";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { useCopy } from "useCopy";
|
import { useCopy } from "@/useCopy";
|
||||||
|
|
||||||
export interface CopyProps {
|
export interface CopyProps {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { NostrLink } from "@snort/system";
|
import { NostrLink } from "@snort/system";
|
||||||
import { useReactions } from "@snort/system-react";
|
import { useReactions } from "@snort/system-react";
|
||||||
|
|
||||||
import { useArticles } from "Feed/ArticlesFeed";
|
import { useArticles } from "@/Feed/ArticlesFeed";
|
||||||
import { orderDescending } from "SnortUtils";
|
import { orderDescending } from "@/SnortUtils";
|
||||||
import Note from "../Event/Note";
|
import Note from "../Event/Note";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { DeckContext } from "Pages/DeckLayout";
|
import { DeckContext } from "@/Pages/DeckLayout";
|
||||||
|
|
||||||
export default function Articles() {
|
export default function Articles() {
|
||||||
const data = useArticles();
|
const data = useArticles();
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
import Avatar from "Element/User/Avatar";
|
import Avatar from "@/Element/User/Avatar";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import "./Nav.css";
|
import "./Nav.css";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { NoteCreatorButton } from "Element/Event/NoteCreatorButton";
|
import { NoteCreatorButton } from "@/Element/Event/NoteCreatorButton";
|
||||||
import { ProfileLink } from "Element/User/ProfileLink";
|
import { ProfileLink } from "@/Element/User/ProfileLink";
|
||||||
|
|
||||||
export function DeckNav() {
|
export function DeckNav() {
|
||||||
const { publicKey } = useLogin();
|
const { publicKey } = useLogin();
|
||||||
|
@ -3,8 +3,8 @@ import { useEffect, useState } from "react";
|
|||||||
import { FormattedMessage, FormattedNumber } from "react-intl";
|
import { FormattedMessage, FormattedNumber } from "react-intl";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
interface Token {
|
interface Token {
|
||||||
token: Array<{
|
token: Array<{
|
||||||
@ -107,7 +107,7 @@ export default function CashuNuts({ token }: { token: string }) {
|
|||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="<h1>{n}</h1> Cashu sats"
|
defaultMessage="<h1>{n}</h1> Cashu sats" id="6/SF6e"
|
||||||
values={{
|
values={{
|
||||||
h1: c => <h1>{c}</h1>,
|
h1: c => <h1>{c}</h1>,
|
||||||
n: <FormattedNumber value={amount} />,
|
n: <FormattedNumber value={amount} />,
|
||||||
@ -116,7 +116,7 @@ export default function CashuNuts({ token }: { token: string }) {
|
|||||||
</div>
|
</div>
|
||||||
<small className="xs w-max">
|
<small className="xs w-max">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="<b>Mint:</b> {url}"
|
defaultMessage="<b>Mint:</b> {url}" id="zwb6LR"
|
||||||
values={{
|
values={{
|
||||||
b: c => <b>{c}</b>,
|
b: c => <b>{c}</b>,
|
||||||
url: new URL(cashu.token[0].mint).hostname,
|
url: new URL(cashu.token[0].mint).hostname,
|
||||||
@ -129,7 +129,7 @@ export default function CashuNuts({ token }: { token: string }) {
|
|||||||
<Icon name="copy" />
|
<Icon name="copy" />
|
||||||
</button>
|
</button>
|
||||||
<button onClick={e => redeemToken(e, token)}>
|
<button onClick={e => redeemToken(e, token)}>
|
||||||
<FormattedMessage defaultMessage="Redeem" description="Button: Redeem Cashu token" />
|
<FormattedMessage defaultMessage="Redeem" id="XrSk2j" description="Button: Redeem Cashu token" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,9 +5,9 @@ import { useMemo } from "react";
|
|||||||
import { decodeInvoice } from "@snort/shared";
|
import { decodeInvoice } from "@snort/shared";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import SendSats from "Element/SendSats";
|
import SendSats from "@/Element/SendSats";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { useWallet } from "Wallet";
|
import { useWallet } from "@/Wallet";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export default function Invoice(props: InvoiceProps) {
|
|||||||
{description && <p>{description}</p>}
|
{description && <p>{description}</p>}
|
||||||
{isPaid ? (
|
{isPaid ? (
|
||||||
<div className="paid">
|
<div className="paid">
|
||||||
<FormattedMessage defaultMessage="Paid" />
|
<FormattedMessage defaultMessage="Paid" id="u/vOPu" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<button disabled={isExpired} type="button" onClick={payInvoice}>
|
<button disabled={isExpired} type="button" onClick={payInvoice}>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import "./LinkPreview.css";
|
import "./LinkPreview.css";
|
||||||
import { CSSProperties, useEffect, useState } from "react";
|
import { CSSProperties, useEffect, useState } from "react";
|
||||||
|
|
||||||
import Spinner from "Icons/Spinner";
|
import Spinner from "@/Icons/Spinner";
|
||||||
import SnortApi, { LinkPreviewData } from "External/SnortApi";
|
import SnortApi, { LinkPreviewData } from "@/External/SnortApi";
|
||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import { MediaElement } from "Element/Embed/MediaElement";
|
import { MediaElement } from "@/Element/Embed/MediaElement";
|
||||||
|
|
||||||
async function fetchUrlPreviewInfo(url: string) {
|
async function fetchUrlPreviewInfo(url: string) {
|
||||||
const api = new SnortApi();
|
const api = new SnortApi();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import { Magnet } from "SnortUtils";
|
import { Magnet } from "@/SnortUtils";
|
||||||
|
|
||||||
interface MagnetLinkProps {
|
interface MagnetLinkProps {
|
||||||
magnet: Magnet;
|
magnet: Magnet;
|
||||||
@ -10,7 +10,7 @@ const MagnetLink = ({ magnet }: MagnetLinkProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className="note-invoice">
|
<div className="note-invoice">
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Magnet Link" />
|
<FormattedMessage defaultMessage="Magnet Link" id="Gcn9NQ" />
|
||||||
</h4>
|
</h4>
|
||||||
<a href={magnet.raw} rel="noreferrer">
|
<a href={magnet.raw} rel="noreferrer">
|
||||||
{magnet.dn ?? magnet.infoHash}
|
{magnet.dn ?? magnet.infoHash}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ProxyImg } from "Element/ProxyImg";
|
import { ProxyImg } from "@/Element/ProxyImg";
|
||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
interface MediaElementProps {
|
interface MediaElementProps {
|
||||||
|
@ -2,9 +2,9 @@ import { NostrLink, NostrPrefix } from "@snort/system";
|
|||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
import { useHover } from "@uidotdev/usehooks";
|
import { useHover } from "@uidotdev/usehooks";
|
||||||
|
|
||||||
import DisplayName from "Element/User/DisplayName";
|
import DisplayName from "@/Element/User/DisplayName";
|
||||||
import { ProfileCard } from "Element/User/ProfileCard";
|
import { ProfileCard } from "@/Element/User/ProfileCard";
|
||||||
import { ProfileLink } from "Element/User/ProfileLink";
|
import { ProfileLink } from "@/Element/User/ProfileLink";
|
||||||
|
|
||||||
export default function Mention({ link }: { link: NostrLink }) {
|
export default function Mention({ link }: { link: NostrLink }) {
|
||||||
const [ref, hovering] = useHover<HTMLAnchorElement>();
|
const [ref, hovering] = useHover<HTMLAnchorElement>();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { MixCloudRegex } from "Const";
|
import { MixCloudRegex } from "@/Const";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
|
||||||
const MixCloudEmbed = ({ link }: { link: string }) => {
|
const MixCloudEmbed = ({ link }: { link: string }) => {
|
||||||
const feedPath = (MixCloudRegex.test(link) && RegExp.$1) + "%2F" + (MixCloudRegex.test(link) && RegExp.$2);
|
const feedPath = (MixCloudRegex.test(link) && RegExp.$1) + "%2F" + (MixCloudRegex.test(link) && RegExp.$2);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { NostrPrefix, tryParseNostrLink } from "@snort/system";
|
import { NostrPrefix, tryParseNostrLink } from "@snort/system";
|
||||||
|
|
||||||
import Mention from "Element/Embed/Mention";
|
import Mention from "@/Element/Embed/Mention";
|
||||||
import NoteQuote from "Element/Event/NoteQuote";
|
import NoteQuote from "@/Element/Event/NoteQuote";
|
||||||
|
|
||||||
export default function NostrLink({ link, depth }: { link: string; depth?: number }) {
|
export default function NostrLink({ link, depth }: { link: string; depth?: number }) {
|
||||||
const nav = tryParseNostrLink(link);
|
const nav = tryParseNostrLink(link);
|
||||||
|
@ -2,15 +2,15 @@ import { NostrEvent } from "@snort/system";
|
|||||||
import { FormattedMessage, FormattedNumber } from "react-intl";
|
import { FormattedMessage, FormattedNumber } from "react-intl";
|
||||||
import { LNURL } from "@snort/shared";
|
import { LNURL } from "@snort/shared";
|
||||||
|
|
||||||
import { dedupe, findTag, hexToBech32, getDisplayName } from "SnortUtils";
|
import { dedupe, findTag, hexToBech32, getDisplayName } from "@/SnortUtils";
|
||||||
import FollowListBase from "Element/User/FollowListBase";
|
import FollowListBase from "@/Element/User/FollowListBase";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
import { useWallet } from "Wallet";
|
import { useWallet } from "@/Wallet";
|
||||||
import { Toastore } from "Toaster";
|
import { Toastore } from "@/Toaster";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { WalletInvoiceState } from "Wallet";
|
import { WalletInvoiceState } from "@/Wallet";
|
||||||
|
|
||||||
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
export default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {
|
||||||
const wallet = useWallet();
|
const wallet = useWallet();
|
||||||
@ -42,7 +42,7 @@ export default function PubkeyList({ ev, className }: { ev: NostrEvent; classNam
|
|||||||
Toastore.push({
|
Toastore.push({
|
||||||
element: (
|
element: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Sent {n} sats to {name}"
|
defaultMessage="Sent {n} sats to {name}" id="Ig9/a1"
|
||||||
values={{
|
values={{
|
||||||
n: amtSend,
|
n: amtSend,
|
||||||
name: getDisplayName(profile, pk),
|
name: getDisplayName(profile, pk),
|
||||||
@ -70,7 +70,7 @@ export default function PubkeyList({ ev, className }: { ev: NostrEvent; classNam
|
|||||||
<>
|
<>
|
||||||
<AsyncButton className="mr5 secondary" onClick={() => zapAll()}>
|
<AsyncButton className="mr5 secondary" onClick={() => zapAll()}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Zap all {n} sats"
|
defaultMessage="Zap all {n} sats" id="IVbtTS"
|
||||||
values={{
|
values={{
|
||||||
n: <FormattedNumber value={login.appData.item.preferences.defaultZapAmount * ids.length} />,
|
n: <FormattedNumber value={login.appData.item.preferences.defaultZapAmount * ids.length} />,
|
||||||
}}
|
}}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { TidalRegex } from "Const";
|
import { TidalRegex } from "@/Const";
|
||||||
|
|
||||||
// Re-use dom parser across instances of TidalEmbed
|
// Re-use dom parser across instances of TidalEmbed
|
||||||
const domParser = new DOMParser();
|
const domParser = new DOMParser();
|
||||||
|
@ -2,8 +2,8 @@ import "./ZapstrEmbed.css";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { NostrEvent, NostrLink } from "@snort/system";
|
import { NostrEvent, NostrLink } from "@snort/system";
|
||||||
|
|
||||||
import { ProxyImg } from "Element/ProxyImg";
|
import { ProxyImg } from "@/Element/ProxyImg";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
export default function ZapstrEmbed({ ev }: { ev: NostrEvent }) {
|
export default function ZapstrEmbed({ ev }: { ev: NostrEvent }) {
|
||||||
@ -31,7 +31,7 @@ export default function ZapstrEmbed({ ev }: { ev: NostrEvent }) {
|
|||||||
</div>
|
</div>
|
||||||
<Link to={`https://zapstr.live/?track=${link}`} target="_blank">
|
<Link to={`https://zapstr.live/?track=${link}`} target="_blank">
|
||||||
<button>
|
<button>
|
||||||
<FormattedMessage defaultMessage="Open on Zapstr" />
|
<FormattedMessage defaultMessage="Open on Zapstr" id="Lu5/Bj" />
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Progress from "Element/Progress";
|
import Progress from "@/Element/Progress";
|
||||||
import { UploadProgress } from "Upload";
|
import { UploadProgress } from "@/Upload";
|
||||||
|
|
||||||
export default function FileUploadProgress({ progress }: { progress: Array<UploadProgress> }) {
|
export default function FileUploadProgress({ progress }: { progress: Array<UploadProgress> }) {
|
||||||
return (
|
return (
|
||||||
|
@ -10,7 +10,7 @@ const HiddenNote = ({ children }: { children: React.ReactNode }) => {
|
|||||||
<div className="card note hidden-note">
|
<div className="card note hidden-note">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage defaultMessage="This note has been muted" />
|
<FormattedMessage defaultMessage="This note has been muted" id="qfmMQh" />
|
||||||
</p>
|
</p>
|
||||||
<button type="button" onClick={() => setShow(true)}>
|
<button type="button" onClick={() => setShow(true)}>
|
||||||
<FormattedMessage {...messages.Show} />
|
<FormattedMessage {...messages.Show} />
|
||||||
|
@ -4,11 +4,11 @@ import { FormattedMessage, FormattedNumber } from "react-intl";
|
|||||||
import { NostrLink, TaggedNostrEvent } from "@snort/system";
|
import { NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||||
import { useEventReactions } from "@snort/system-react";
|
import { useEventReactions } from "@snort/system-react";
|
||||||
|
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
import Text from "Element/Text";
|
import Text from "@/Element/Text";
|
||||||
import { Markdown } from "./Markdown";
|
import { Markdown } from "./Markdown";
|
||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "@/Element/User/ProfilePreview";
|
||||||
import NoteFooter from "./NoteFooter";
|
import NoteFooter from "./NoteFooter";
|
||||||
import NoteTime from "./NoteTime";
|
import NoteTime from "./NoteTime";
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ export function LongFormText(props: LongFormTextProps) {
|
|||||||
<div className="flex g8">
|
<div className="flex g8">
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="{n} mins to read"
|
defaultMessage="{n} mins to read" id="zm6qS1"
|
||||||
values={{
|
values={{
|
||||||
n: <FormattedNumber value={readTime().mins} />,
|
n: <FormattedNumber value={readTime().mins} />,
|
||||||
}}
|
}}
|
||||||
@ -102,12 +102,12 @@ export function LongFormText(props: LongFormTextProps) {
|
|||||||
<div>‧</div>
|
<div>‧</div>
|
||||||
{!reading && (
|
{!reading && (
|
||||||
<div className="pointer" onClick={() => readArticle()}>
|
<div className="pointer" onClick={() => readArticle()}>
|
||||||
<FormattedMessage defaultMessage="Listen to this article" />
|
<FormattedMessage defaultMessage="Listen to this article" id="nihgfo" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{reading && (
|
{reading && (
|
||||||
<div className="pointer" onClick={() => stopReading()}>
|
<div className="pointer" onClick={() => stopReading()}>
|
||||||
<FormattedMessage defaultMessage="Stop listening" />
|
<FormattedMessage defaultMessage="Stop listening" id="U1aPPi" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,8 +6,8 @@ import { marked, Token } from "marked";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import markedFootnote, { Footnotes, Footnote, FootnoteRef } from "marked-footnote";
|
import markedFootnote, { Footnotes, Footnote, FootnoteRef } from "marked-footnote";
|
||||||
|
|
||||||
import { ProxyImg } from "Element/ProxyImg";
|
import { ProxyImg } from "@/Element/ProxyImg";
|
||||||
import NostrLink from "Element/Embed/NostrLink";
|
import NostrLink from "@/Element/Embed/NostrLink";
|
||||||
|
|
||||||
interface MarkdownProps {
|
interface MarkdownProps {
|
||||||
content: string;
|
content: string;
|
||||||
|
@ -2,10 +2,10 @@ import { FormattedMessage } from "react-intl";
|
|||||||
import { NostrEvent, NostrLink } from "@snort/system";
|
import { NostrEvent, NostrLink } from "@snort/system";
|
||||||
import { useEventFeed } from "@snort/system-react";
|
import { useEventFeed } from "@snort/system-react";
|
||||||
|
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
import Reveal from "Element/Event/Reveal";
|
import Reveal from "@/Element/Event/Reveal";
|
||||||
import { MediaElement } from "Element/Embed/MediaElement";
|
import { MediaElement } from "@/Element/Embed/MediaElement";
|
||||||
|
|
||||||
export default function NostrFileHeader({ link }: { link: NostrLink }) {
|
export default function NostrFileHeader({ link }: { link: NostrLink }) {
|
||||||
const ev = useEventFeed(link);
|
const ev = useEventFeed(link);
|
||||||
@ -26,14 +26,14 @@ export function NostrFileElement({ ev }: { ev: NostrEvent }) {
|
|||||||
|
|
||||||
if (u && m) {
|
if (u && m) {
|
||||||
return (
|
return (
|
||||||
<Reveal message={<FormattedMessage defaultMessage="Click to load content from {link}" values={{ link: u }} />}>
|
<Reveal message={<FormattedMessage defaultMessage="Click to load content from {link}" id="lsNFM1" values={{ link: u }} />}>
|
||||||
<MediaElement mime={m} url={u} sha256={x} magnet={magnet} blurHash={blurHash} />
|
<MediaElement mime={m} url={u} sha256={x} magnet={magnet} blurHash={blurHash} />
|
||||||
</Reveal>
|
</Reveal>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<b className="error">
|
<b className="error">
|
||||||
<FormattedMessage defaultMessage="Unknown file header: {name}" values={{ name: ev.content }} />
|
<FormattedMessage defaultMessage="Unknown file header: {name}" id="PamNxw" values={{ name: ev.content }} />
|
||||||
</b>
|
</b>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import "./Note.css";
|
import "./Note.css";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { EventKind, NostrEvent, TaggedNostrEvent } from "@snort/system";
|
import { EventKind, NostrEvent, TaggedNostrEvent } from "@snort/system";
|
||||||
import { NostrFileElement } from "Element/Event/NostrFileHeader";
|
import { NostrFileElement } from "@/Element/Event/NostrFileHeader";
|
||||||
import ZapstrEmbed from "Element/Embed/ZapstrEmbed";
|
import ZapstrEmbed from "@/Element/Embed/ZapstrEmbed";
|
||||||
import PubkeyList from "Element/Embed/PubkeyList";
|
import PubkeyList from "@/Element/Embed/PubkeyList";
|
||||||
import { LiveEvent } from "Element/LiveEvent";
|
import { LiveEvent } from "@/Element/LiveEvent";
|
||||||
import { ZapGoal } from "Element/Event/ZapGoal";
|
import { ZapGoal } from "@/Element/Event/ZapGoal";
|
||||||
import NoteReaction from "Element/Event/NoteReaction";
|
import NoteReaction from "@/Element/Event/NoteReaction";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "@/Element/User/ProfilePreview";
|
||||||
import { NoteInner } from "./NoteInner";
|
import { NoteInner } from "./NoteInner";
|
||||||
import { LongFormText } from "./LongFormText";
|
import { LongFormText } from "./LongFormText";
|
||||||
|
|
||||||
|
@ -3,13 +3,13 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||||||
import { removeUndefined, unwrap } from "@snort/shared";
|
import { removeUndefined, unwrap } from "@snort/shared";
|
||||||
import { NostrEvent, OkResponse } from "@snort/system";
|
import { NostrEvent, OkResponse } from "@snort/system";
|
||||||
|
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { getRelayName, sanitizeRelayUrl } from "SnortUtils";
|
import { getRelayName, sanitizeRelayUrl } from "@/SnortUtils";
|
||||||
import { removeRelay } from "Login";
|
import { removeRelay } from "@/Login";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { saveRelays } from "Pages/settings/Relays";
|
import { saveRelays } from "@/Pages/settings/Relays";
|
||||||
|
|
||||||
export function NoteBroadcaster({
|
export function NoteBroadcaster({
|
||||||
evs,
|
evs,
|
||||||
@ -73,7 +73,7 @@ export function NoteBroadcaster({
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col g16">
|
<div className="flex flex-col g16">
|
||||||
<h3>
|
<h3>
|
||||||
<FormattedMessage defaultMessage="Sending notes and other stuff" />
|
<FormattedMessage defaultMessage="Sending notes and other stuff" id="ugyJnE" />
|
||||||
</h3>
|
</h3>
|
||||||
{results
|
{results
|
||||||
.filter(a => a.message !== "Duplicate request")
|
.filter(a => a.message !== "Duplicate request")
|
||||||
@ -91,7 +91,7 @@ export function NoteBroadcaster({
|
|||||||
onClick={() => retryPublish(r)}
|
onClick={() => retryPublish(r)}
|
||||||
className="p4 br-compact flex items-center secondary"
|
className="p4 br-compact flex items-center secondary"
|
||||||
title={formatMessage({
|
title={formatMessage({
|
||||||
defaultMessage: "Retry publishing",
|
defaultMessage: "Retry publishing", id: '9kSari',
|
||||||
})}>
|
})}>
|
||||||
<Icon name="refresh-ccw-01" />
|
<Icon name="refresh-ccw-01" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
@ -99,7 +99,7 @@ export function NoteBroadcaster({
|
|||||||
onClick={() => removeRelayFromResult(r)}
|
onClick={() => removeRelayFromResult(r)}
|
||||||
className="p4 br-compact flex items-center secondary"
|
className="p4 br-compact flex items-center secondary"
|
||||||
title={formatMessage({
|
title={formatMessage({
|
||||||
defaultMessage: "Remove from my relays",
|
defaultMessage: "Remove from my relays", id: 'UJTWqI',
|
||||||
})}>
|
})}>
|
||||||
<Icon name="trash-01" className="trash-icon" />
|
<Icon name="trash-01" className="trash-icon" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
@ -109,7 +109,7 @@ export function NoteBroadcaster({
|
|||||||
))}
|
))}
|
||||||
<div className="flex-row g8">
|
<div className="flex-row g8">
|
||||||
<button type="button" onClick={() => onClose()}>
|
<button type="button" onClick={() => onClose()}>
|
||||||
<FormattedMessage defaultMessage="Close" />
|
<FormattedMessage defaultMessage="Close" id="rbrahO" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,15 +3,15 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||||||
import { HexKey, NostrLink, NostrPrefix, TaggedNostrEvent } from "@snort/system";
|
import { HexKey, NostrLink, NostrPrefix, TaggedNostrEvent } from "@snort/system";
|
||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
|
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { setPinned, setBookmarked } from "Login";
|
import { setPinned, setBookmarked } from "@/Login";
|
||||||
import messages from "Element/messages";
|
import messages from "@/Element/messages";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { ReBroadcaster } from "../ReBroadcaster";
|
import { ReBroadcaster } from "../ReBroadcaster";
|
||||||
import SnortApi from "External/SnortApi";
|
import SnortApi from "@/External/SnortApi";
|
||||||
import { SubscriptionType, getCurrentSubscription } from "Subscription";
|
import { SubscriptionType, getCurrentSubscription } from "@/Subscription";
|
||||||
|
|
||||||
export interface NoteTranslation {
|
export interface NoteTranslation {
|
||||||
text: string;
|
text: string;
|
||||||
@ -170,7 +170,7 @@ export function NoteContextMenu({ ev, ...props }: NosteContextMenuProps) {
|
|||||||
)}
|
)}
|
||||||
<MenuItem onClick={handleReBroadcastButtonClick}>
|
<MenuItem onClick={handleReBroadcastButtonClick}>
|
||||||
<Icon name="relay" />
|
<Icon name="relay" />
|
||||||
<FormattedMessage defaultMessage="Broadcast Event" />
|
<FormattedMessage defaultMessage="Broadcast Event" id="Gxcr08" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{ev.pubkey !== login.publicKey && !login.readonly && (
|
{ev.pubkey !== login.publicKey && !login.readonly && (
|
||||||
<MenuItem onClick={() => block(ev.pubkey)}>
|
<MenuItem onClick={() => block(ev.pubkey)}>
|
||||||
|
@ -4,28 +4,28 @@ import { EventKind, NostrPrefix, TaggedNostrEvent, EventBuilder, tryParseNostrLi
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { TagsInput } from "react-tag-input-component";
|
import { TagsInput } from "react-tag-input-component";
|
||||||
|
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { appendDedupe, openFile } from "SnortUtils";
|
import { appendDedupe, openFile } from "@/SnortUtils";
|
||||||
import Textarea from "Element/Textarea";
|
import Textarea from "@/Element/Textarea";
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "@/Upload";
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
|
|
||||||
import { ClipboardEventHandler, DragEvent, useEffect, useState } from "react";
|
import { ClipboardEventHandler, DragEvent, useEffect, useState } from "react";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { GetPowWorker } from "index";
|
import { GetPowWorker } from "@/index";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
import { AsyncIcon } from "Element/AsyncIcon";
|
import { AsyncIcon } from "@/Element/AsyncIcon";
|
||||||
import { fetchNip05Pubkey } from "@snort/shared";
|
import { fetchNip05Pubkey } from "@snort/shared";
|
||||||
import { ZapTarget } from "Zapper";
|
import { ZapTarget } from "@/Zapper";
|
||||||
import { useNoteCreator } from "State/NoteCreator";
|
import { useNoteCreator } from "@/State/NoteCreator";
|
||||||
import { NoteBroadcaster } from "./NoteBroadcaster";
|
import { NoteBroadcaster } from "./NoteBroadcaster";
|
||||||
import FileUploadProgress from "./FileUpload";
|
import FileUploadProgress from "./FileUpload";
|
||||||
import { ToggleSwitch } from "Icons/Toggle";
|
import { ToggleSwitch } from "@/Icons/Toggle";
|
||||||
import NostrBandApi from "External/NostrBand";
|
import NostrBandApi from "@/External/NostrBand";
|
||||||
import { useLocale } from "IntlProvider";
|
import { useLocale } from "@/IntlProvider";
|
||||||
|
|
||||||
export function NoteCreator() {
|
export function NoteCreator() {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
@ -52,7 +52,7 @@ export function NoteCreator() {
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
formatMessage(
|
formatMessage(
|
||||||
{
|
{
|
||||||
defaultMessage: "Failed to parse zap split: {input}",
|
defaultMessage: "Failed to parse zap split: {input}", id: 'sZQzjQ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: s.value,
|
input: s.value,
|
||||||
@ -69,7 +69,7 @@ export function NoteCreator() {
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
formatMessage(
|
formatMessage(
|
||||||
{
|
{
|
||||||
defaultMessage: "Failed to parse zap split: {input}",
|
defaultMessage: "Failed to parse zap split: {input}", id: 'sZQzjQ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: s.value,
|
input: s.value,
|
||||||
@ -81,7 +81,7 @@ export function NoteCreator() {
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
formatMessage(
|
formatMessage(
|
||||||
{
|
{
|
||||||
defaultMessage: "Invalid zap split: {input}",
|
defaultMessage: "Invalid zap split: {input}", id: '8Y6bZQ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: s.value,
|
input: s.value,
|
||||||
@ -258,12 +258,12 @@ export function NoteCreator() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Poll Options" />
|
<FormattedMessage defaultMessage="Poll Options" id="vhlWFg" />
|
||||||
</h4>
|
</h4>
|
||||||
{note.pollOptions?.map((a, i) => (
|
{note.pollOptions?.map((a, i) => (
|
||||||
<div className="form-group w-max" key={`po-${i}`}>
|
<div className="form-group w-max" key={`po-${i}`}>
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage defaultMessage="Option: {n}" values={{ n: i + 1 }} />
|
<FormattedMessage defaultMessage="Option: {n}" id="mfe8RW" values={{ n: i + 1 }} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="text" value={a} onChange={e => changePollOption(i, e.target.value)} />
|
<input type="text" value={a} onChange={e => changePollOption(i, e.target.value)} />
|
||||||
@ -353,24 +353,24 @@ export function NoteCreator() {
|
|||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Custom Relays" />
|
<FormattedMessage defaultMessage="Custom Relays" id="EcZF24" />
|
||||||
</h4>
|
</h4>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage defaultMessage="Send note to a subset of your write relays" />
|
<FormattedMessage defaultMessage="Send note to a subset of your write relays" id="th5lxp" />
|
||||||
</p>
|
</p>
|
||||||
{renderRelayCustomisation()}
|
{renderRelayCustomisation()}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col g8">
|
<div className="flex flex-col g8">
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Zap Splits" />
|
<FormattedMessage defaultMessage="Zap Splits" id="5CB6zB" />
|
||||||
</h4>
|
</h4>
|
||||||
<FormattedMessage defaultMessage="Zaps on this note will be split to the following users." />
|
<FormattedMessage defaultMessage="Zaps on this note will be split to the following users." id="LwYmVi" />
|
||||||
<div className="flex flex-col g8">
|
<div className="flex flex-col g8">
|
||||||
{[...(note.zapSplits ?? [])].map((v, i, arr) => (
|
{[...(note.zapSplits ?? [])].map((v, i, arr) => (
|
||||||
<div className="flex items-center g8">
|
<div className="flex items-center g8">
|
||||||
<div className="flex flex-col f-4 g4">
|
<div className="flex flex-col f-4 g4">
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Recipient" />
|
<FormattedMessage defaultMessage="Recipient" id="8Rkoyb" />
|
||||||
</h4>
|
</h4>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -380,12 +380,12 @@ export function NoteCreator() {
|
|||||||
v => (v.zapSplits = arr.map((vv, ii) => (ii === i ? { ...vv, value: e.target.value } : vv))),
|
v => (v.zapSplits = arr.map((vv, ii) => (ii === i ? { ...vv, value: e.target.value } : vv))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
placeholder={formatMessage({ defaultMessage: "npub / nprofile / nostr address" })}
|
placeholder={formatMessage({ defaultMessage: "npub / nprofile / nostr address", id: 'WvGmZT' })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col f-1 g4">
|
<div className="flex flex-col f-1 g4">
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Weight" />
|
<FormattedMessage defaultMessage="Weight" id="zCb8fX" />
|
||||||
</h4>
|
</h4>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
@ -415,18 +415,18 @@ export function NoteCreator() {
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
note.update(v => (v.zapSplits = [...(v.zapSplits ?? []), { type: "pubkey", value: "", weight: 1 }]))
|
note.update(v => (v.zapSplits = [...(v.zapSplits ?? []), { type: "pubkey", value: "", weight: 1 }]))
|
||||||
}>
|
}>
|
||||||
<FormattedMessage defaultMessage="Add" />
|
<FormattedMessage defaultMessage="Add" id="2/2yg+" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span className="warning">
|
<span className="warning">
|
||||||
<FormattedMessage defaultMessage="Not all clients support this, you may still receive some zaps as if zap splits was not configured" />
|
<FormattedMessage defaultMessage="Not all clients support this, you may still receive some zaps as if zap splits was not configured" id="6bgpn+" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col g8">
|
<div className="flex flex-col g8">
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Sensitive Content" />
|
<FormattedMessage defaultMessage="Sensitive Content" id="bQdA2k" />
|
||||||
</h4>
|
</h4>
|
||||||
<FormattedMessage defaultMessage="Users must accept the content warning to show the content of your note." />
|
<FormattedMessage defaultMessage="Users must accept the content warning to show the content of your note." id="UUPFlt" />
|
||||||
<input
|
<input
|
||||||
className="w-max"
|
className="w-max"
|
||||||
type="text"
|
type="text"
|
||||||
@ -435,11 +435,11 @@ export function NoteCreator() {
|
|||||||
maxLength={50}
|
maxLength={50}
|
||||||
minLength={1}
|
minLength={1}
|
||||||
placeholder={formatMessage({
|
placeholder={formatMessage({
|
||||||
defaultMessage: "Reason",
|
defaultMessage: "Reason", id: 'AkCxS/',
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<span className="warning">
|
<span className="warning">
|
||||||
<FormattedMessage defaultMessage="Not all clients support this yet" />
|
<FormattedMessage defaultMessage="Not all clients support this yet" id="gXgY3+" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -473,7 +473,7 @@ export function NoteCreator() {
|
|||||||
className={classNames("note-creator-icon", { active: note.advanced })}
|
className={classNames("note-creator-icon", { active: note.advanced })}
|
||||||
/>
|
/>
|
||||||
<span className="sm:inline hidden">
|
<span className="sm:inline hidden">
|
||||||
<FormattedMessage defaultMessage="Preview" />
|
<FormattedMessage defaultMessage="Preview" id="TJo5E6" />
|
||||||
</span>
|
</span>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
onClick={() => loadPreview()}
|
onClick={() => loadPreview()}
|
||||||
@ -483,10 +483,10 @@ export function NoteCreator() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex g8">
|
<div className="flex g8">
|
||||||
<button className="secondary" onClick={cancel}>
|
<button className="secondary" onClick={cancel}>
|
||||||
<FormattedMessage defaultMessage="Cancel" />
|
<FormattedMessage defaultMessage="Cancel" id="47FYwb" />
|
||||||
</button>
|
</button>
|
||||||
<AsyncButton onClick={onSubmit} className="primary">
|
<AsyncButton onClick={onSubmit} className="primary">
|
||||||
{note.replyTo ? <FormattedMessage defaultMessage="Reply" /> : <FormattedMessage defaultMessage="Send" />}
|
{note.replyTo ? <FormattedMessage defaultMessage="Reply" id="9HU8vw" /> : <FormattedMessage defaultMessage="Send" id="9WRlF4" />}
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -536,7 +536,7 @@ export function NoteCreator() {
|
|||||||
{note.replyTo && (
|
{note.replyTo && (
|
||||||
<>
|
<>
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Reply To" />
|
<FormattedMessage defaultMessage="Reply To" id="8ED/4u" />
|
||||||
</h4>
|
</h4>
|
||||||
<Note
|
<Note
|
||||||
data={note.replyTo}
|
data={note.replyTo}
|
||||||
@ -555,7 +555,7 @@ export function NoteCreator() {
|
|||||||
{note.quote && (
|
{note.quote && (
|
||||||
<>
|
<>
|
||||||
<h4>
|
<h4>
|
||||||
<FormattedMessage defaultMessage="Quote Repost" />
|
<FormattedMessage defaultMessage="Quote Repost" id="C7642/" />
|
||||||
</h4>
|
</h4>
|
||||||
<Note
|
<Note
|
||||||
data={note.quote}
|
data={note.quote}
|
||||||
@ -597,13 +597,13 @@ export function NoteCreator() {
|
|||||||
value={note.hashTags}
|
value={note.hashTags}
|
||||||
onChange={e => note.update(s => (s.hashTags = e))}
|
onChange={e => note.update(s => (s.hashTags = e))}
|
||||||
placeHolder={formatMessage({
|
placeHolder={formatMessage({
|
||||||
defaultMessage: "Add up to 4 hashtags",
|
defaultMessage: "Add up to 4 hashtags", id: 'AIgmDy',
|
||||||
})}
|
})}
|
||||||
separators={["Enter", ","]}
|
separators={["Enter", ","]}
|
||||||
/>
|
/>
|
||||||
{note.hashTags.length > 4 && (
|
{note.hashTags.length > 4 && (
|
||||||
<small className="warning">
|
<small className="warning">
|
||||||
<FormattedMessage defaultMessage="Try to use less than 5 hashtags to stay on topic 🙏" />
|
<FormattedMessage defaultMessage="Try to use less than 5 hashtags to stay on topic 🙏" id="d8gpCh" />
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
<TrendingHashTagsLine onClick={t => note.update(s => (s.hashTags = appendDedupe(s.hashTags, [t])))} />
|
<TrendingHashTagsLine onClick={t => note.update(s => (s.hashTags = appendDedupe(s.hashTags, [t])))} />
|
||||||
@ -652,7 +652,7 @@ function TrendingHashTagsLine(props: { onClick: (tag: string) => void }) {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col g4">
|
<div className="flex flex-col g4">
|
||||||
<small>
|
<small>
|
||||||
<FormattedMessage defaultMessage="Popular Hashtags" />
|
<FormattedMessage defaultMessage="Popular Hashtags" id="ddd3JX" />
|
||||||
</small>
|
</small>
|
||||||
<div className="flex g4 flex-wrap">
|
<div className="flex g4 flex-wrap">
|
||||||
{hashtags.slice(0, 5).map(a => (
|
{hashtags.slice(0, 5).map(a => (
|
||||||
|
@ -3,11 +3,11 @@ import { useRef, useMemo } from "react";
|
|||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { isFormElement } from "SnortUtils";
|
import { isFormElement } from "@/SnortUtils";
|
||||||
import useKeyboardShortcut from "Hooks/useKeyboardShortcut";
|
import useKeyboardShortcut from "@/Hooks/useKeyboardShortcut";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { useNoteCreator } from "State/NoteCreator";
|
import { useNoteCreator } from "@/State/NoteCreator";
|
||||||
import { NoteCreator } from "./NoteCreator";
|
import { NoteCreator } from "./NoteCreator";
|
||||||
|
|
||||||
export const NoteCreatorButton = ({ className }: { className?: string }) => {
|
export const NoteCreatorButton = ({ className }: { className?: string }) => {
|
||||||
|
@ -7,20 +7,20 @@ import { useUserProfile } from "@snort/system-react";
|
|||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { delay, findTag, getDisplayName } from "SnortUtils";
|
import { delay, findTag, getDisplayName } from "@/SnortUtils";
|
||||||
import SendSats from "Element/SendSats";
|
import SendSats from "@/Element/SendSats";
|
||||||
import { ZapsSummary } from "Element/Event/Zap";
|
import { ZapsSummary } from "@/Element/Event/Zap";
|
||||||
import { AsyncIcon, AsyncIconProps } from "Element/AsyncIcon";
|
import { AsyncIcon, AsyncIconProps } from "@/Element/AsyncIcon";
|
||||||
|
|
||||||
import { useWallet } from "Wallet";
|
import { useWallet } from "@/Wallet";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { useInteractionCache } from "Hooks/useInteractionCache";
|
import { useInteractionCache } from "@/Hooks/useInteractionCache";
|
||||||
import { ZapPoolController } from "ZapPoolController";
|
import { ZapPoolController } from "@/ZapPoolController";
|
||||||
import { Zapper, ZapTarget } from "Zapper";
|
import { Zapper, ZapTarget } from "@/Zapper";
|
||||||
import { useNoteCreator } from "State/NoteCreator";
|
import { useNoteCreator } from "@/State/NoteCreator";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
const pow = findTag(ev, "nonce") ? countLeadingZeros(ev.id) : undefined;
|
const pow = findTag(ev, "nonce") ? countLeadingZeros(ev.id) : undefined;
|
||||||
if (pow) {
|
if (pow) {
|
||||||
return (
|
return (
|
||||||
<AsyncFooterIcon title={formatMessage({ defaultMessage: "Proof of Work" })} iconName="diamond" value={pow} />
|
<AsyncFooterIcon title={formatMessage({ defaultMessage: "Proof of Work", id: 'grQ+mI' })} iconName="diamond" value={pow} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
<AsyncFooterIcon
|
<AsyncFooterIcon
|
||||||
className={didZap ? "reacted text-nostr-orange" : "hover:text-nostr-orange"}
|
className={didZap ? "reacted text-nostr-orange" : "hover:text-nostr-orange"}
|
||||||
{...longPress()}
|
{...longPress()}
|
||||||
title={formatMessage({ defaultMessage: "Zap" })}
|
title={formatMessage({ defaultMessage: "Zap", id: 'fBI91o' })}
|
||||||
iconName={canFastZap ? "zapFast" : "zap"}
|
iconName={canFastZap ? "zapFast" : "zap"}
|
||||||
value={zapTotal}
|
value={zapTotal}
|
||||||
onClick={e => fastZap(e)}
|
onClick={e => fastZap(e)}
|
||||||
@ -217,7 +217,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
<AsyncFooterIcon
|
<AsyncFooterIcon
|
||||||
className={hasReposted() ? "reacted text-nostr-blue" : "hover:text-nostr-blue"}
|
className={hasReposted() ? "reacted text-nostr-blue" : "hover:text-nostr-blue"}
|
||||||
iconName="repeat"
|
iconName="repeat"
|
||||||
title={formatMessage({ defaultMessage: "Repost" })}
|
title={formatMessage({ defaultMessage: "Repost", id: 'JeoS4y' })}
|
||||||
value={reposts.length}
|
value={reposts.length}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
</div>
|
</div>
|
||||||
<MenuItem onClick={() => repost()} disabled={hasReposted()}>
|
<MenuItem onClick={() => repost()} disabled={hasReposted()}>
|
||||||
<Icon name="repeat" />
|
<Icon name="repeat" />
|
||||||
<FormattedMessage defaultMessage="Repost" />
|
<FormattedMessage defaultMessage="Repost" id="JeoS4y" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@ -243,7 +243,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
})
|
})
|
||||||
}>
|
}>
|
||||||
<Icon name="edit" />
|
<Icon name="edit" />
|
||||||
<FormattedMessage defaultMessage="Quote Repost" />
|
<FormattedMessage defaultMessage="Quote Repost" id="C7642/" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
@ -258,7 +258,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
<AsyncFooterIcon
|
<AsyncFooterIcon
|
||||||
className={reacted ? "reacted text-nostr-red" : "hover:text-nostr-red"}
|
className={reacted ? "reacted text-nostr-red" : "hover:text-nostr-red"}
|
||||||
iconName={reacted ? "heart-solid" : "heart"}
|
iconName={reacted ? "heart-solid" : "heart"}
|
||||||
title={formatMessage({ defaultMessage: "Like" })}
|
title={formatMessage({ defaultMessage: "Like", id: 'qtWLmt' })}
|
||||||
value={positive.length}
|
value={positive.length}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (readonly) return;
|
if (readonly) return;
|
||||||
@ -274,7 +274,7 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
<AsyncFooterIcon
|
<AsyncFooterIcon
|
||||||
className={note.show ? "reacted text-nostr-purple" : "hover:text-nostr-purple"}
|
className={note.show ? "reacted text-nostr-purple" : "hover:text-nostr-purple"}
|
||||||
iconName="reply"
|
iconName="reply"
|
||||||
title={formatMessage({ defaultMessage: "Reply" })}
|
title={formatMessage({ defaultMessage: "Reply", id: '9HU8vw' })}
|
||||||
value={props.replies ?? 0}
|
value={props.replies ?? 0}
|
||||||
onClick={async () => handleReplyButtonClick()}
|
onClick={async () => handleReplyButtonClick()}
|
||||||
/>
|
/>
|
||||||
@ -308,14 +308,15 @@ export default function NoteFooter(props: NoteFooterProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AsyncFooterIcon = forwardRef((props: AsyncIconProps & { value: number }) => {
|
const AsyncFooterIcon = forwardRef((props: AsyncIconProps & { value: number }, ref) => {
|
||||||
const mergedProps = {
|
const mergedProps = {
|
||||||
...props,
|
...props,
|
||||||
iconSize: 18,
|
iconSize: 18,
|
||||||
className: classNames("transition duration-200 ease-in-out reaction-pill", props.className),
|
className: classNames("transition duration-200 ease-in-out reaction-pill", props.className),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncIcon {...mergedProps}>
|
<AsyncIcon ref={ref} {...mergedProps}>
|
||||||
{props.value > 0 && <div className="reaction-pill-number">{formatShort(props.value)}</div>}
|
{props.value > 0 && <div className="reaction-pill-number">{formatShort(props.value)}</div>}
|
||||||
</AsyncIcon>
|
</AsyncIcon>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "./Note.css";
|
import "./Note.css";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
|
|
||||||
interface NoteGhostProps {
|
interface NoteGhostProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -6,26 +6,26 @@ import classNames from "classnames";
|
|||||||
import { EventExt, EventKind, HexKey, NostrLink, NostrPrefix, TaggedNostrEvent } from "@snort/system";
|
import { EventExt, EventKind, HexKey, NostrLink, NostrPrefix, TaggedNostrEvent } from "@snort/system";
|
||||||
import { useEventReactions } from "@snort/system-react";
|
import { useEventReactions } from "@snort/system-react";
|
||||||
|
|
||||||
import { findTag, hexToBech32 } from "SnortUtils";
|
import { findTag, hexToBech32 } from "@/SnortUtils";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { NoteContextMenu, NoteTranslation } from "./NoteContextMenu";
|
import { NoteContextMenu, NoteTranslation } from "./NoteContextMenu";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { setBookmarked, setPinned } from "Login";
|
import { setBookmarked, setPinned } from "@/Login";
|
||||||
import Text from "../Text";
|
import Text from "../Text";
|
||||||
import Reveal from "./Reveal";
|
import Reveal from "./Reveal";
|
||||||
import Poll from "./Poll";
|
import Poll from "./Poll";
|
||||||
import ProfileImage from "../User/ProfileImage";
|
import ProfileImage from "../User/ProfileImage";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import NoteTime from "./NoteTime";
|
import NoteTime from "./NoteTime";
|
||||||
import NoteFooter from "./NoteFooter";
|
import NoteFooter from "./NoteFooter";
|
||||||
import Reactions from "./Reactions";
|
import Reactions from "./Reactions";
|
||||||
import HiddenNote from "./HiddenNote";
|
import HiddenNote from "./HiddenNote";
|
||||||
import { NoteProps } from "./Note";
|
import { NoteProps } from "./Note";
|
||||||
import { chainKey } from "Hooks/useThreadContext";
|
import { chainKey } from "@/Hooks/useThreadContext";
|
||||||
import { ProfileLink } from "Element/User/ProfileLink";
|
import { ProfileLink } from "@/Element/User/ProfileLink";
|
||||||
|
|
||||||
export function NoteInner(props: NoteProps) {
|
export function NoteInner(props: NoteProps) {
|
||||||
const { data: ev, related, highlight, options: opt, ignoreModeration = false, className } = props;
|
const { data: ev, related, highlight, options: opt, ignoreModeration = false, className } = props;
|
||||||
@ -118,7 +118,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
message={
|
message={
|
||||||
<>
|
<>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="The author has marked this note as a <i>sensitive topic</i>"
|
defaultMessage="The author has marked this note as a <i>sensitive topic</i>" id="StKzTE"
|
||||||
values={{
|
values={{
|
||||||
i: c => <i>{c}</i>,
|
i: c => <i>{c}</i>,
|
||||||
}}
|
}}
|
||||||
@ -127,7 +127,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
<>
|
<>
|
||||||
|
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Reason: <i>{reason}</i>"
|
defaultMessage="Reason: <i>{reason}</i>" id="6OSOXl"
|
||||||
values={{
|
values={{
|
||||||
i: c => <i>{c}</i>,
|
i: c => <i>{c}</i>,
|
||||||
reason: contentWarning[1],
|
reason: contentWarning[1],
|
||||||
@ -136,7 +136,7 @@ export function NoteInner(props: NoteProps) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FormattedMessage defaultMessage="Click here to load anyway" />
|
<FormattedMessage defaultMessage="Click here to load anyway" id="IoQq+a" />
|
||||||
</>
|
</>
|
||||||
}>
|
}>
|
||||||
{innerContent}
|
{innerContent}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { NostrLink } from "@snort/system";
|
import { NostrLink } from "@snort/system";
|
||||||
import { useEventFeed } from "@snort/system-react";
|
import { useEventFeed } from "@snort/system-react";
|
||||||
|
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
|
|
||||||
export default function NoteQuote({ link, depth }: { link: NostrLink; depth?: number }) {
|
export default function NoteQuote({ link, depth }: { link: NostrLink; depth?: number }) {
|
||||||
const ev = useEventFeed(link);
|
const ev = useEventFeed(link);
|
||||||
|
@ -3,11 +3,11 @@ import { Link } from "react-router-dom";
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { EventKind, NostrEvent, TaggedNostrEvent, NostrPrefix, EventExt } from "@snort/system";
|
import { EventKind, NostrEvent, TaggedNostrEvent, NostrPrefix, EventExt } from "@snort/system";
|
||||||
|
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import { eventLink, hexToBech32, getDisplayName } from "SnortUtils";
|
import { eventLink, hexToBech32, getDisplayName } from "@/SnortUtils";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
import { useInView } from "react-intersection-observer";
|
import { useInView } from "react-intersection-observer";
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ export default function NoteReaction(props: NoteReactionProps) {
|
|||||||
<div className="flex g4">
|
<div className="flex g4">
|
||||||
<Icon name="repeat" size={18} />
|
<Icon name="repeat" size={18} />
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="{name} reposted"
|
defaultMessage="{name} reposted" id="+xliwN"
|
||||||
values={{
|
values={{
|
||||||
name: getDisplayName(profile, ev.pubkey),
|
name: getDisplayName(profile, ev.pubkey),
|
||||||
}}
|
}}
|
||||||
|
@ -4,13 +4,13 @@ import { useState } from "react";
|
|||||||
import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
|
import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { useWallet } from "Wallet";
|
import { useWallet } from "@/Wallet";
|
||||||
import { unwrap } from "SnortUtils";
|
import { unwrap } from "@/SnortUtils";
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import Spinner from "Icons/Spinner";
|
import Spinner from "@/Icons/Spinner";
|
||||||
import SendSats from "Element/SendSats";
|
import SendSats from "@/Element/SendSats";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
|
||||||
interface PollProps {
|
interface PollProps {
|
||||||
ev: TaggedNostrEvent;
|
ev: TaggedNostrEvent;
|
||||||
@ -51,7 +51,7 @@ export default function Poll(props: PollProps) {
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
formatMessage(
|
formatMessage(
|
||||||
{
|
{
|
||||||
defaultMessage: "Can't vote with {amount} sats, please set a different default zap amount",
|
defaultMessage: "Can't vote with {amount} sats, please set a different default zap amount", id: 'NepkXH',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount,
|
amount,
|
||||||
@ -75,7 +75,7 @@ export default function Poll(props: PollProps) {
|
|||||||
if (!svc.canZap) {
|
if (!svc.canZap) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
defaultMessage: "Can't vote because LNURL service does not support zaps",
|
defaultMessage: "Can't vote because LNURL service does not support zaps", id: 'fOksnD',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ export default function Poll(props: PollProps) {
|
|||||||
} else {
|
} else {
|
||||||
setError(
|
setError(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
defaultMessage: "Failed to send vote",
|
defaultMessage: "Failed to send vote", id: 'g985Wp',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ export default function Poll(props: PollProps) {
|
|||||||
<div className="flex justify-between p">
|
<div className="flex justify-between p">
|
||||||
<small>
|
<small>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="You are voting with {amount} sats"
|
defaultMessage="You are voting with {amount} sats" id="3qnJlS"
|
||||||
values={{
|
values={{
|
||||||
amount: formatShort(prefs.defaultZapAmount),
|
amount: formatShort(prefs.defaultZapAmount),
|
||||||
}}
|
}}
|
||||||
@ -123,13 +123,13 @@ export default function Poll(props: PollProps) {
|
|||||||
</small>
|
</small>
|
||||||
<button type="button" onClick={() => setTallyBy(s => (s !== "zaps" ? "zaps" : "pubkeys"))}>
|
<button type="button" onClick={() => setTallyBy(s => (s !== "zaps" ? "zaps" : "pubkeys"))}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Votes by {type}"
|
defaultMessage="Votes by {type}" id="xIcAOU"
|
||||||
values={{
|
values={{
|
||||||
type:
|
type:
|
||||||
tallyBy === "zaps" ? (
|
tallyBy === "zaps" ? (
|
||||||
<FormattedMessage defaultMessage="zap" />
|
<FormattedMessage defaultMessage="zap" id="5BVs2e" />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage defaultMessage="user" />
|
<FormattedMessage defaultMessage="user" id="sUNhQE" />
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -4,12 +4,12 @@ import { useState, useMemo, useEffect } from "react";
|
|||||||
import { useIntl, FormattedMessage } from "react-intl";
|
import { useIntl, FormattedMessage } from "react-intl";
|
||||||
import { TaggedNostrEvent, ParsedZap } from "@snort/system";
|
import { TaggedNostrEvent, ParsedZap } from "@snort/system";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { Tab } from "Element/Tabs";
|
import { Tab } from "@/Element/Tabs";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import Tabs from "Element/Tabs";
|
import Tabs from "@/Element/Tabs";
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ const Reactions = ({ show, setShow, positive, negative, reposts, zaps }: Reactio
|
|||||||
pubkey={z.anonZap ? "" : z.sender}
|
pubkey={z.anonZap ? "" : z.sender}
|
||||||
subHeader={<div title={z.content}>{z.content}</div>}
|
subHeader={<div title={z.content}>{z.content}</div>}
|
||||||
link={z.anonZap ? "" : undefined}
|
link={z.anonZap ? "" : undefined}
|
||||||
overrideUsername={z.anonZap ? formatMessage({ defaultMessage: "Anonymous" }) : undefined}
|
overrideUsername={z.anonZap ? formatMessage({ defaultMessage: "Anonymous", id: 'LXxsbk' }) : undefined}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { WarningNotice } from "Element/WarningNotice";
|
import { WarningNotice } from "@/Element/WarningNotice";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
interface RevealProps {
|
interface RevealProps {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import { FileExtensionRegex } from "Const";
|
import { FileExtensionRegex } from "@/Const";
|
||||||
import Reveal from "Element/Event/Reveal";
|
import Reveal from "@/Element/Event/Reveal";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { MediaElement } from "Element/Embed/MediaElement";
|
import { MediaElement } from "@/Element/Embed/MediaElement";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
interface RevealMediaProps {
|
interface RevealMediaProps {
|
||||||
@ -57,7 +57,7 @@ export default function RevealMedia(props: RevealMediaProps) {
|
|||||||
<Reveal
|
<Reveal
|
||||||
message={
|
message={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody."
|
defaultMessage="You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody." id="HhcAVH"
|
||||||
values={{
|
values={{
|
||||||
i: i => <i>{i}</i>,
|
i: i => <i>{i}</i>,
|
||||||
a: a => <Link to="/settings/preferences">{a}</Link>,
|
a: a => <Link to="/settings/preferences">{a}</Link>,
|
||||||
|
@ -14,7 +14,7 @@ const ShowMore = ({ text, onClick, className = "" }: ShowMoreProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className="show-more-container">
|
<div className="show-more-container">
|
||||||
<button className={classNames("show-more", className)} onClick={onClick}>
|
<button className={classNames("show-more", className)} onClick={onClick}>
|
||||||
{text || <FormattedMessage defaultMessage="Show More" />}
|
{text || <FormattedMessage defaultMessage="Show More" id="O8Z8t9" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -5,12 +5,12 @@ import { useNavigate, useParams } from "react-router-dom";
|
|||||||
import { TaggedNostrEvent, u256, NostrPrefix, EventExt, parseNostrLink, NostrLink } from "@snort/system";
|
import { TaggedNostrEvent, u256, NostrPrefix, EventExt, parseNostrLink, NostrLink } from "@snort/system";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { getAllLinkReactions, getLinkReactions } from "SnortUtils";
|
import { getAllLinkReactions, getLinkReactions } from "@/SnortUtils";
|
||||||
import BackButton from "Element/BackButton";
|
import BackButton from "@/Element/BackButton";
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import NoteGhost from "Element/Event/NoteGhost";
|
import NoteGhost from "@/Element/Event/NoteGhost";
|
||||||
import Collapsed from "Element/Collapsed";
|
import Collapsed from "@/Element/Collapsed";
|
||||||
import { ThreadContext, ThreadContextWrapper, chainKey } from "Hooks/useThreadContext";
|
import { ThreadContext, ThreadContextWrapper, chainKey } from "@/Hooks/useThreadContext";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -303,11 +303,11 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parentText = formatMessage({
|
const parentText = formatMessage({
|
||||||
defaultMessage: "Parent",
|
defaultMessage: "Parent", id: 'ADmfQT',
|
||||||
description: "Link to parent note in thread",
|
description: "Link to parent note in thread",
|
||||||
});
|
});
|
||||||
const backText = formatMessage({
|
const backText = formatMessage({
|
||||||
defaultMessage: "Back",
|
defaultMessage: "Back", id: 'jfV8Wr',
|
||||||
description: "Navigate back button on threads view",
|
description: "Navigate back button on threads view",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ import { useMemo } from "react";
|
|||||||
import { ParsedZap } from "@snort/system";
|
import { ParsedZap } from "@snort/system";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { unwrap } from "SnortUtils";
|
import { unwrap } from "@/SnortUtils";
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import Text from "Element/Text";
|
import Text from "@/Element/Text";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ export const ZapsSummary = ({ zaps }: ZapsSummaryProps) => {
|
|||||||
<ProfileImage
|
<ProfileImage
|
||||||
pubkey={anonZap ? "" : sender}
|
pubkey={anonZap ? "" : sender}
|
||||||
showFollowDistance={false}
|
showFollowDistance={false}
|
||||||
overrideUsername={anonZap ? formatMessage({ defaultMessage: "Anonymous" }) : undefined}
|
overrideUsername={anonZap ? formatMessage({ defaultMessage: "Anonymous", id: 'LXxsbk' }) : undefined}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{restZaps.length > 0 ? (
|
{restZaps.length > 0 ? (
|
||||||
|
@ -3,9 +3,9 @@ import { useState } from "react";
|
|||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import SendSats from "Element/SendSats";
|
import SendSats from "@/Element/SendSats";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { ZapTarget } from "Zapper";
|
import { ZapTarget } from "@/Zapper";
|
||||||
|
|
||||||
const ZapButton = ({
|
const ZapButton = ({
|
||||||
pubkey,
|
pubkey,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import "./ZapGoal.css";
|
import "./ZapGoal.css";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { NostrEvent, NostrLink } from "@snort/system";
|
import { NostrEvent, NostrLink } from "@snort/system";
|
||||||
import useZapsFeed from "Feed/ZapsFeed";
|
import useZapsFeed from "@/Feed/ZapsFeed";
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import SendSats from "../SendSats";
|
import SendSats from "../SendSats";
|
||||||
import { Zapper } from "Zapper";
|
import { Zapper } from "@/Zapper";
|
||||||
import Progress from "Element/Progress";
|
import Progress from "@/Element/Progress";
|
||||||
import { FormattedNumber } from "react-intl";
|
import { FormattedNumber } from "react-intl";
|
||||||
|
|
||||||
export function ZapGoal({ ev }: { ev: NostrEvent }) {
|
export function ZapGoal({ ev }: { ev: NostrEvent }) {
|
||||||
|
@ -3,10 +3,10 @@ import { FormattedMessage } from "react-intl";
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { TaggedNostrEvent, EventKind } from "@snort/system";
|
import { TaggedNostrEvent, EventKind } from "@snort/system";
|
||||||
|
|
||||||
import { dedupeByPubkey, findTag } from "SnortUtils";
|
import { dedupeByPubkey, findTag } from "@/SnortUtils";
|
||||||
import useTimelineFeed, { TimelineFeed, TimelineSubject } from "Feed/TimelineFeed";
|
import useTimelineFeed, { TimelineFeed, TimelineSubject } from "@/Feed/TimelineFeed";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import { LiveStreams } from "Element/LiveStreams";
|
import { LiveStreams } from "@/Element/LiveStreams";
|
||||||
import { TimelineRenderer } from "./TimelineFragment";
|
import { TimelineRenderer } from "./TimelineFragment";
|
||||||
import { unixNow } from "@snort/shared";
|
import { unixNow } from "@snort/shared";
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ const Timeline = (props: TimelineProps) => {
|
|||||||
{(props.loadMore === undefined || props.loadMore === true) && (
|
{(props.loadMore === undefined || props.loadMore === true) && (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<button type="button" onClick={() => feed.loadMore()}>
|
<button type="button" onClick={() => feed.loadMore()}>
|
||||||
<FormattedMessage defaultMessage="Load more" />
|
<FormattedMessage defaultMessage="Load more" id="00LcfG" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -5,14 +5,14 @@ import { EventKind, NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/syste
|
|||||||
import { unixNow } from "@snort/shared";
|
import { unixNow } from "@snort/shared";
|
||||||
import { SnortContext, useReactions } from "@snort/system-react";
|
import { SnortContext, useReactions } from "@snort/system-react";
|
||||||
|
|
||||||
import { dedupeByPubkey, findTag, orderDescending } from "SnortUtils";
|
import { dedupeByPubkey, findTag, orderDescending } from "@/SnortUtils";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import { FollowsFeed } from "Cache";
|
import { FollowsFeed } from "@/Cache";
|
||||||
import { LiveStreams } from "Element/LiveStreams";
|
import { LiveStreams } from "@/Element/LiveStreams";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { TimelineRenderer } from "./TimelineFragment";
|
import { TimelineRenderer } from "./TimelineFragment";
|
||||||
import useHashtagsFeed from "Feed/HashtagsFeed";
|
import useHashtagsFeed from "@/Feed/HashtagsFeed";
|
||||||
import { ShowMoreInView } from "Element/Event/ShowMore";
|
import { ShowMoreInView } from "@/Element/Event/ShowMore";
|
||||||
|
|
||||||
export interface TimelineFollowsProps {
|
export interface TimelineFollowsProps {
|
||||||
postsOnly: boolean;
|
postsOnly: boolean;
|
||||||
|
@ -3,10 +3,10 @@ import { FormattedMessage } from "react-intl";
|
|||||||
import { useInView } from "react-intersection-observer";
|
import { useInView } from "react-intersection-observer";
|
||||||
import { TaggedNostrEvent } from "@snort/system";
|
import { TaggedNostrEvent } from "@snort/system";
|
||||||
|
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
|
|
||||||
export interface TimelineFragment {
|
export interface TimelineFragment {
|
||||||
events: Array<TaggedNostrEvent>;
|
events: Array<TaggedNostrEvent>;
|
||||||
@ -39,7 +39,7 @@ export function TimelineRenderer(props: TimelineRendererProps) {
|
|||||||
return <ProfileImage pubkey={p} showUsername={false} link={""} showFollowDistance={false} />;
|
return <ProfileImage pubkey={p} showUsername={false} link={""} showFollowDistance={false} />;
|
||||||
})}
|
})}
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="{n} new {n, plural, =1 {note} other {notes}}"
|
defaultMessage="{n} new {n, plural, =1 {note} other {notes}}" id="3t3kok"
|
||||||
values={{ n: props.latest.length }}
|
values={{ n: props.latest.length }}
|
||||||
/>
|
/>
|
||||||
<Icon name="arrowUp" />
|
<Icon name="arrowUp" />
|
||||||
@ -52,7 +52,7 @@ export function TimelineRenderer(props: TimelineRendererProps) {
|
|||||||
return <ProfileImage pubkey={p} showUsername={false} link={""} showFollowDistance={false} />;
|
return <ProfileImage pubkey={p} showUsername={false} link={""} showFollowDistance={false} />;
|
||||||
})}
|
})}
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="{n} new {n, plural, =1 {note} other {notes}}"
|
defaultMessage="{n} new {n, plural, =1 {note} other {notes}}" id="3t3kok"
|
||||||
values={{ n: props.latest.length }}
|
values={{ n: props.latest.length }}
|
||||||
/>
|
/>
|
||||||
<Icon name="arrowUp" />
|
<Icon name="arrowUp" />
|
||||||
|
@ -11,18 +11,18 @@ import {
|
|||||||
AppleMusicRegex,
|
AppleMusicRegex,
|
||||||
NostrNestsRegex,
|
NostrNestsRegex,
|
||||||
WavlakeRegex,
|
WavlakeRegex,
|
||||||
} from "Const";
|
} from "@/Const";
|
||||||
import { magnetURIDecode } from "SnortUtils";
|
import { magnetURIDecode } from "@/SnortUtils";
|
||||||
import SoundCloudEmbed from "Element/Embed/SoundCloudEmded";
|
import SoundCloudEmbed from "@/Element/Embed/SoundCloudEmded";
|
||||||
import MixCloudEmbed from "Element/Embed/MixCloudEmbed";
|
import MixCloudEmbed from "@/Element/Embed/MixCloudEmbed";
|
||||||
import SpotifyEmbed from "Element/Embed/SpotifyEmbed";
|
import SpotifyEmbed from "@/Element/Embed/SpotifyEmbed";
|
||||||
import TidalEmbed from "Element/Embed/TidalEmbed";
|
import TidalEmbed from "@/Element/Embed/TidalEmbed";
|
||||||
import TwitchEmbed from "Element/Embed/TwitchEmbed";
|
import TwitchEmbed from "@/Element/Embed/TwitchEmbed";
|
||||||
import AppleMusicEmbed from "Element/Embed/AppleMusicEmbed";
|
import AppleMusicEmbed from "@/Element/Embed/AppleMusicEmbed";
|
||||||
import WavlakeEmbed from "Element/Embed/WavlakeEmbed";
|
import WavlakeEmbed from "@/Element/Embed/WavlakeEmbed";
|
||||||
import LinkPreview from "Element/Embed/LinkPreview";
|
import LinkPreview from "@/Element/Embed/LinkPreview";
|
||||||
import NostrLink from "Element/Embed/NostrLink";
|
import NostrLink from "@/Element/Embed/NostrLink";
|
||||||
import MagnetLink from "Element/Embed/MagnetLink";
|
import MagnetLink from "@/Element/Embed/MagnetLink";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
interface HypeTextProps {
|
interface HypeTextProps {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import Icon, { IconProps } from "Icons/Icon";
|
import Icon, { IconProps } from "@/Icons/Icon";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
interface IconButtonProps {
|
interface IconButtonProps {
|
||||||
|
@ -6,10 +6,10 @@ export default function AccountName({ name = "", link = true }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage defaultMessage="Username" />: <b>{name}</b>
|
<FormattedMessage defaultMessage="Username" id="JCIgkj" />: <b>{name}</b>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage defaultMessage="Short link" />:{" "}
|
<FormattedMessage defaultMessage="Short link" id="rx1i0i" />:{" "}
|
||||||
{link ? (
|
{link ? (
|
||||||
<a
|
<a
|
||||||
href={`https://iris.to/${name}`}
|
href={`https://iris.to/${name}`}
|
||||||
@ -24,7 +24,7 @@ export default function AccountName({ name = "", link = true }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<FormattedMessage defaultMessage="Nostr address (nip05)" />: <b>{name}@iris.to</b>
|
<FormattedMessage defaultMessage="Nostr address (nip05)" id="BjNwZW" />: <b>{name}@iris.to</b>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -2,9 +2,9 @@ import { mapEventToProfile } from "@snort/system";
|
|||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
|
|
||||||
import AccountName from "./AccountName";
|
import AccountName from "./AccountName";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
||||||
@ -61,12 +61,12 @@ export default function ActiveAccount({ name = "", setAsPrimary = () => {} }) {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="negative">
|
<div className="negative">
|
||||||
<FormattedMessage defaultMessage="You have an active iris.to account" />:
|
<FormattedMessage defaultMessage="You have an active iris.to account" id="UrKTqQ" />:
|
||||||
<AccountName name={name} />
|
<AccountName name={name} />
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<button type="button" onClick={onClick}>
|
<button type="button" onClick={onClick}>
|
||||||
<FormattedMessage defaultMessage="Set as primary Nostr address (nip05)" />
|
<FormattedMessage defaultMessage="Set as primary Nostr address (nip05)" id="MiMipu" />
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { Component, FormEvent } from "react";
|
import { Component, FormEvent } from "react";
|
||||||
import { LoginStore } from "Login";
|
import { LoginStore } from "@/Login";
|
||||||
|
|
||||||
import AccountName from "./AccountName";
|
import AccountName from "./AccountName";
|
||||||
import ActiveAccount from "./ActiveAccount";
|
import ActiveAccount from "./ActiveAccount";
|
||||||
import ReservedAccount from "./ReservedAccount";
|
import ReservedAccount from "./ReservedAccount";
|
||||||
import { ProfileLoader } from "index";
|
import { ProfileLoader } from "@/index";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { injectIntl } from "react-intl";
|
import { injectIntl } from "react-intl";
|
||||||
import messages from "Element/messages";
|
import messages from "@/Element/messages";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -71,7 +71,7 @@ class IrisAccount extends Component<Props> {
|
|||||||
view = (
|
view = (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage defaultMessage="Register an Iris username" /> (iris.to/username)
|
<FormattedMessage defaultMessage="Register an Iris username" id="kEZUR8" /> (iris.to/username)
|
||||||
</p>
|
</p>
|
||||||
<form onSubmit={e => this.showChallenge(e)}>
|
<form onSubmit={e => this.showChallenge(e)}>
|
||||||
<div className="flex g8">
|
<div className="flex g8">
|
||||||
@ -83,14 +83,14 @@ class IrisAccount extends Component<Props> {
|
|||||||
onInput={e => this.onNewUserNameChange(e)}
|
onInput={e => this.onNewUserNameChange(e)}
|
||||||
/>
|
/>
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
<FormattedMessage defaultMessage="Register" />
|
<FormattedMessage defaultMessage="Register" id="deEeEI" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{this.state.newUserNameValid ? (
|
{this.state.newUserNameValid ? (
|
||||||
<>
|
<>
|
||||||
<span className="success">
|
<span className="success">
|
||||||
<FormattedMessage defaultMessage="Username is available" />
|
<FormattedMessage defaultMessage="Username is available" id="EcfIwB" />
|
||||||
</span>
|
</span>
|
||||||
<AccountName name={this.state.newUserName} link={false} />
|
<AccountName name={this.state.newUserName} link={false} />
|
||||||
</>
|
</>
|
||||||
@ -106,7 +106,7 @@ class IrisAccount extends Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3>
|
<h3>
|
||||||
<FormattedMessage defaultMessage="Iris.to account" />
|
<FormattedMessage defaultMessage="Iris.to account" id="Mzizei" />
|
||||||
</h3>
|
</h3>
|
||||||
{view}
|
{view}
|
||||||
<p>
|
<p>
|
||||||
|
@ -6,19 +6,19 @@ export default function ReservedAccount({ name = "", enableReserved = () => {},
|
|||||||
<div>
|
<div>
|
||||||
<p className="success">
|
<p className="success">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Username iris.to/<b>{name}</b> is reserved for you!"
|
defaultMessage="Username iris.to/<b>{name}</b> is reserved for you!" id="Zff6lu"
|
||||||
values={{ name, b: s => <b>{s}</b> }}
|
values={{ name, b: s => <b>{s}</b> }}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<AccountName name={name} link={false} />
|
<AccountName name={name} link={false} />
|
||||||
<p>
|
<p>
|
||||||
<button className="btn btn-sm btn-primary" onClick={() => enableReserved()}>
|
<button className="btn btn-sm btn-primary" onClick={() => enableReserved()}>
|
||||||
<FormattedMessage defaultMessage="Yes please" />
|
<FormattedMessage defaultMessage="Yes please" id="VcwrfF" />
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<button className="btn btn-sm btn-neutral" onClick={() => declineReserved()}>
|
<button className="btn btn-sm btn-neutral" onClick={() => declineReserved()}>
|
||||||
<FormattedMessage defaultMessage="No thanks" />
|
<FormattedMessage defaultMessage="No thanks" id="c+JYNI" />
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,9 +2,9 @@ import { NostrEvent, NostrLink } from "@snort/system";
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
import ProfileImage from "./User/ProfileImage";
|
import ProfileImage from "./User/ProfileImage";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
||||||
const title = findTag(ev, "title");
|
const title = findTag(ev, "title");
|
||||||
@ -19,7 +19,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
|||||||
<div className="flex g4">
|
<div className="flex g4">
|
||||||
<Icon name="signal-01" />
|
<Icon name="signal-01" />
|
||||||
<b className="uppercase">
|
<b className="uppercase">
|
||||||
<FormattedMessage defaultMessage="Live" />
|
<FormattedMessage defaultMessage="Live" id="Dn82AL" />
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -27,7 +27,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
|||||||
case "ended": {
|
case "ended": {
|
||||||
return (
|
return (
|
||||||
<b className="uppercase">
|
<b className="uppercase">
|
||||||
<FormattedMessage defaultMessage="Ended" />
|
<FormattedMessage defaultMessage="Ended" id="TP/cMX" />
|
||||||
</b>
|
</b>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
|||||||
return (
|
return (
|
||||||
<Link to={link} target="_blank">
|
<Link to={link} target="_blank">
|
||||||
<button type="button">
|
<button type="button">
|
||||||
<FormattedMessage defaultMessage="Join Stream" />
|
<FormattedMessage defaultMessage="Join Stream" id="GQPtfk" />
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@ -60,7 +60,7 @@ export function LiveEvent({ ev }: { ev: NostrEvent }) {
|
|||||||
return (
|
return (
|
||||||
<Link to={link} target="_blank">
|
<Link to={link} target="_blank">
|
||||||
<button type="button">
|
<button type="button">
|
||||||
<FormattedMessage defaultMessage="Watch Replay" />
|
<FormattedMessage defaultMessage="Watch Replay" id="6/hB3S" />
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import "./LiveStreams.css";
|
import "./LiveStreams.css";
|
||||||
import { NostrEvent, NostrLink } from "@snort/system";
|
import { NostrEvent, NostrLink } from "@snort/system";
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
import { CSSProperties, useMemo } from "react";
|
import { CSSProperties, useMemo } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
export function LiveStreams({ evs }: { evs: Array<NostrEvent> }) {
|
export function LiveStreams({ evs }: { evs: Array<NostrEvent> }) {
|
||||||
const streams = useMemo(() => {
|
const streams = useMemo(() => {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { logout } from "Login";
|
import { logout } from "@/Login";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
export default function LogoutButton() {
|
export default function LogoutButton() {
|
||||||
|
@ -3,8 +3,8 @@ import { useIntl, FormattedMessage } from "react-intl";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { UserMetadata, mapEventToProfile } from "@snort/system";
|
import { UserMetadata, mapEventToProfile } from "@snort/system";
|
||||||
|
|
||||||
import { unwrap } from "SnortUtils";
|
import { unwrap } from "@/SnortUtils";
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import {
|
import {
|
||||||
ServiceProvider,
|
ServiceProvider,
|
||||||
ServiceConfig,
|
ServiceConfig,
|
||||||
@ -13,16 +13,16 @@ import {
|
|||||||
ServiceErrorCode,
|
ServiceErrorCode,
|
||||||
HandleRegisterResponse,
|
HandleRegisterResponse,
|
||||||
CheckRegisterResponse,
|
CheckRegisterResponse,
|
||||||
} from "Nip05/ServiceProvider";
|
} from "@/Nip05/ServiceProvider";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
import SendSats from "Element/SendSats";
|
import SendSats from "@/Element/SendSats";
|
||||||
import Copy from "Element/Copy";
|
import Copy from "@/Element/Copy";
|
||||||
import { useUserProfile } from "@snort/system-react";
|
import { useUserProfile } from "@snort/system-react";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { debounce } from "SnortUtils";
|
import { debounce } from "@/SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import SnortServiceProvider from "Nip05/SnortServiceProvider";
|
import SnortServiceProvider from "@/Nip05/SnortServiceProvider";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ export default function Nip5Service(props: Nip05ServiceProps) {
|
|||||||
: startBuy(handle, domain)
|
: startBuy(handle, domain)
|
||||||
}>
|
}>
|
||||||
{props.forSubscription ? (
|
{props.forSubscription ? (
|
||||||
<FormattedMessage defaultMessage="Claim Now" />
|
<FormattedMessage defaultMessage="Claim Now" id="FdhSU2" />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage {...messages.BuyNow} />
|
<FormattedMessage {...messages.BuyNow} />
|
||||||
)}
|
)}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import AsyncButton from "./AsyncButton";
|
import AsyncButton from "./AsyncButton";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
@ -8,11 +8,11 @@ export function Offline({ onRetry, className }: { onRetry?: () => void | Promise
|
|||||||
<div className={classNames("flex items-center g8", className)}>
|
<div className={classNames("flex items-center g8", className)}>
|
||||||
<Icon name="wifi-off" className="error" />
|
<Icon name="wifi-off" className="error" />
|
||||||
<div className="error">
|
<div className="error">
|
||||||
<FormattedMessage defaultMessage="Offline" />
|
<FormattedMessage defaultMessage="Offline" id="7UOvbT" />
|
||||||
</div>
|
</div>
|
||||||
{onRetry && (
|
{onRetry && (
|
||||||
<AsyncButton onClick={onRetry}>
|
<AsyncButton onClick={onRetry}>
|
||||||
<FormattedMessage defaultMessage="Retry" />
|
<FormattedMessage defaultMessage="Retry" id="62nsdy" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Spinner from "Icons/Spinner";
|
import Spinner from "@/Icons/Spinner";
|
||||||
|
|
||||||
export default function PageSpinner() {
|
export default function PageSpinner() {
|
||||||
return (
|
return (
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import "./PinPrompt.css";
|
import "./PinPrompt.css";
|
||||||
import { ReactNode, useRef, useState } from "react";
|
import { ReactNode, useRef, useState } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { unwrap } from "@snort/shared";
|
import { unwrap } from "@snort/shared";
|
||||||
import { EventPublisher, InvalidPinError, PinEncrypted } from "@snort/system";
|
import { EventPublisher, InvalidPinError, PinEncrypted } from "@snort/system";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { LoginStore, createPublisher, sessionNeedsPin } from "Login";
|
import { LoginStore, createPublisher, sessionNeedsPin } from "@/Login";
|
||||||
import Modal from "./Modal";
|
import Modal from "./Modal";
|
||||||
import AsyncButton from "./AsyncButton";
|
import AsyncButton from "./AsyncButton";
|
||||||
import { GetPowWorker } from "index";
|
import { GetPowWorker } from "@/index";
|
||||||
|
|
||||||
export function PinPrompt({
|
export function PinPrompt({
|
||||||
onResult,
|
onResult,
|
||||||
@ -29,7 +29,7 @@ export function PinPrompt({
|
|||||||
if (pin.length < 4) {
|
if (pin.length < 4) {
|
||||||
setError(
|
setError(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
defaultMessage: "Pin too short",
|
defaultMessage: "Pin too short", id: 'LR1XjT',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -43,7 +43,7 @@ export function PinPrompt({
|
|||||||
if (e instanceof InvalidPinError) {
|
if (e instanceof InvalidPinError) {
|
||||||
setError(
|
setError(
|
||||||
formatMessage({
|
formatMessage({
|
||||||
defaultMessage: "Incorrect pin",
|
defaultMessage: "Incorrect pin", id: 'qz9fty',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else if (e instanceof Error) {
|
} else if (e instanceof Error) {
|
||||||
@ -65,7 +65,7 @@ export function PinPrompt({
|
|||||||
}}>
|
}}>
|
||||||
<div className="flex flex-col g12">
|
<div className="flex flex-col g12">
|
||||||
<h2>
|
<h2>
|
||||||
<FormattedMessage defaultMessage="Enter Pin" />
|
<FormattedMessage defaultMessage="Enter Pin" id="KtsyO0" />
|
||||||
</h2>
|
</h2>
|
||||||
{subTitle ? <div>{subTitle}</div> : null}
|
{subTitle ? <div>{subTitle}</div> : null}
|
||||||
<input
|
<input
|
||||||
@ -79,10 +79,10 @@ export function PinPrompt({
|
|||||||
{error && <b className="error">{error}</b>}
|
{error && <b className="error">{error}</b>}
|
||||||
<div className="flex g8">
|
<div className="flex g8">
|
||||||
<button type="button" onClick={() => onCancel()}>
|
<button type="button" onClick={() => onCancel()}>
|
||||||
<FormattedMessage defaultMessage="Cancel" />
|
<FormattedMessage defaultMessage="Cancel" id="47FYwb" />
|
||||||
</button>
|
</button>
|
||||||
<AsyncButton ref={submitButtonRef} onClick={() => submitPin()} type="submit">
|
<AsyncButton ref={submitButtonRef} onClick={() => submitPin()} type="submit">
|
||||||
<FormattedMessage defaultMessage="Submit" />
|
<FormattedMessage defaultMessage="Submit" id="wSZR47" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -143,7 +143,7 @@ export function LoginUnlock() {
|
|||||||
subTitle={
|
subTitle={
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Enter a pin to encrypt your private key, you must enter this pin every time you open {site}."
|
defaultMessage="Enter a pin to encrypt your private key, you must enter this pin every time you open {site}." id="SLZGPn"
|
||||||
values={{
|
values={{
|
||||||
site: CONFIG.appNameCapitalized,
|
site: CONFIG.appNameCapitalized,
|
||||||
}}
|
}}
|
||||||
@ -161,7 +161,7 @@ export function LoginUnlock() {
|
|||||||
<PinPrompt
|
<PinPrompt
|
||||||
subTitle={
|
subTitle={
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage defaultMessage="Enter pin to unlock your private key" />
|
<FormattedMessage defaultMessage="Enter pin to unlock your private key" id="e7VmYP" />
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
onResult={unlockSession}
|
onResult={unlockSession}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { getUrlHostname } from "SnortUtils";
|
import { getUrlHostname } from "@/SnortUtils";
|
||||||
|
|
||||||
interface ProxyImgProps extends React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
|
interface ProxyImgProps extends React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement> {
|
||||||
size?: number;
|
size?: number;
|
||||||
@ -24,7 +24,7 @@ export const ProxyImg = (props: ProxyImgProps) => {
|
|||||||
setBypass(true);
|
setBypass(true);
|
||||||
}}>
|
}}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Failed to proxy image from {host}, click here to load directly"
|
defaultMessage="Failed to proxy image from {host}, click here to load directly" id="65BmHb"
|
||||||
values={{
|
values={{
|
||||||
host: getUrlHostname(props.src),
|
host: getUrlHostname(props.src),
|
||||||
}}
|
}}
|
||||||
|
@ -3,9 +3,9 @@ import { FormattedMessage } from "react-intl";
|
|||||||
import { TaggedNostrEvent } from "@snort/system";
|
import { TaggedNostrEvent } from "@snort/system";
|
||||||
import { SnortContext } from "@snort/system-react";
|
import { SnortContext } from "@snort/system-react";
|
||||||
|
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import AsyncButton from "./AsyncButton";
|
import AsyncButton from "./AsyncButton";
|
||||||
|
|
||||||
export function ReBroadcaster({ onClose, ev }: { onClose: () => void; ev: TaggedNostrEvent }) {
|
export function ReBroadcaster({ onClose, ev }: { onClose: () => void; ev: TaggedNostrEvent }) {
|
||||||
|
@ -5,13 +5,13 @@ import { RelaySettings } from "@snort/system";
|
|||||||
import { unixNowMs } from "@snort/shared";
|
import { unixNowMs } from "@snort/shared";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import useRelayState from "Feed/RelayState";
|
import useRelayState from "@/Feed/RelayState";
|
||||||
import { SnortContext } from "@snort/system-react";
|
import { SnortContext } from "@snort/system-react";
|
||||||
import { getRelayName, unwrap } from "SnortUtils";
|
import { getRelayName, unwrap } from "@/SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { removeRelay, setRelays } from "Login";
|
import { removeRelay, setRelays } from "@/Login";
|
||||||
import { RelayFavicon } from "./RelaysMetadata";
|
import { RelayFavicon } from "./RelaysMetadata";
|
||||||
import { AsyncIcon } from "Element/AsyncIcon";
|
import { AsyncIcon } from "@/Element/AsyncIcon";
|
||||||
|
|
||||||
export interface RelayProps {
|
export interface RelayProps {
|
||||||
addr: string;
|
addr: string;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import "./RelaysMetadata.css";
|
import "./RelaysMetadata.css";
|
||||||
import Nostrich from "nostrich.webp";
|
import Nostrich from "@/nostrich.webp";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { FullRelaySettings } from "@snort/system";
|
import { FullRelaySettings } from "@snort/system";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
export const RelayFavicon = ({ url }: { url: string }) => {
|
export const RelayFavicon = ({ url }: { url: string }) => {
|
||||||
const cleanUrl = url
|
const cleanUrl = url
|
||||||
|
@ -4,8 +4,8 @@ import { useLocation, useNavigate } from "react-router-dom";
|
|||||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
export type RootTab =
|
export type RootTab =
|
||||||
| "following"
|
| "following"
|
||||||
@ -30,7 +30,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="user-v2" />
|
<Icon name="user-v2" />
|
||||||
<FormattedMessage defaultMessage="Following" />
|
<FormattedMessage defaultMessage="Following" id="cPIKU2" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -41,7 +41,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="fire" />
|
<Icon name="fire" />
|
||||||
<FormattedMessage defaultMessage="Trending Notes" />
|
<FormattedMessage defaultMessage="Trending Notes" id="Ix8l+B" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -52,7 +52,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="message-chat-circle" />
|
<Icon name="message-chat-circle" />
|
||||||
<FormattedMessage defaultMessage="Conversations" />
|
<FormattedMessage defaultMessage="Conversations" id="1udzha" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -63,7 +63,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="user-up" />
|
<Icon name="user-up" />
|
||||||
<FormattedMessage defaultMessage="Trending People" />
|
<FormattedMessage defaultMessage="Trending People" id="CVWeJ6" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -74,7 +74,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="thumbs-up" />
|
<Icon name="thumbs-up" />
|
||||||
<FormattedMessage defaultMessage="Suggested Follows" />
|
<FormattedMessage defaultMessage="Suggested Follows" id="C8HhVE" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -85,7 +85,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="hash" />
|
<Icon name="hash" />
|
||||||
<FormattedMessage defaultMessage="Trending Hashtags" />
|
<FormattedMessage defaultMessage="Trending Hashtags" id="XXm7jJ" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -96,7 +96,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="globe" />
|
<Icon name="globe" />
|
||||||
<FormattedMessage defaultMessage="Global" />
|
<FormattedMessage defaultMessage="Global" id="EWyQH5" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -107,7 +107,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
element: (
|
element: (
|
||||||
<>
|
<>
|
||||||
<Icon name="hash" />
|
<Icon name="hash" />
|
||||||
<FormattedMessage defaultMessage="Topics" />
|
<FormattedMessage defaultMessage="Topics" id="kc79d3" />
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -157,6 +157,7 @@ export function RootTabs({ base }: { base?: string }) {
|
|||||||
.filter(a => a.show)
|
.filter(a => a.show)
|
||||||
.map(a => (
|
.map(a => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
key={a.tab}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(a.path);
|
navigate(a.path);
|
||||||
}}>
|
}}>
|
||||||
|
@ -116,7 +116,7 @@ export default function SearchBox() {
|
|||||||
<div className="search relative">
|
<div className="search relative">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={formatMessage({ defaultMessage: "Search" })}
|
placeholder={formatMessage({ defaultMessage: "Search", id: 'xmcVZ0' })}
|
||||||
className="w-max"
|
className="w-max"
|
||||||
value={search}
|
value={search}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
@ -141,7 +141,7 @@ export default function SearchBox() {
|
|||||||
}`}
|
}`}
|
||||||
onMouseEnter={() => setActiveIndex(0)}
|
onMouseEnter={() => setActiveIndex(0)}
|
||||||
onClick={() => navigate(`/search/${encodeURIComponent(search)}`, { state: { forceRefresh: true } })}>
|
onClick={() => navigate(`/search/${encodeURIComponent(search)}`, { state: { forceRefresh: true } })}>
|
||||||
<FormattedMessage defaultMessage="Search notes" />: <b>{search}</b>
|
<FormattedMessage defaultMessage="Search notes" id="EJbFi7" />: <b>{search}</b>
|
||||||
</div>
|
</div>
|
||||||
{main?.slice(0, MAX_RESULTS).map((result, idx) => (
|
{main?.slice(0, MAX_RESULTS).map((result, idx) => (
|
||||||
<div
|
<div
|
||||||
|
@ -5,18 +5,18 @@ import { useIntl, FormattedMessage } from "react-intl";
|
|||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import { LNURLSuccessAction } from "@snort/shared";
|
import { LNURLSuccessAction } from "@snort/shared";
|
||||||
|
|
||||||
import { formatShort } from "Number";
|
import { formatShort } from "@/Number";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import ProfileImage from "Element/User/ProfileImage";
|
import ProfileImage from "@/Element/User/ProfileImage";
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
import QrCode from "Element/QrCode";
|
import QrCode from "@/Element/QrCode";
|
||||||
import Copy from "Element/Copy";
|
import Copy from "@/Element/Copy";
|
||||||
import { debounce } from "SnortUtils";
|
import { debounce } from "@/SnortUtils";
|
||||||
import { LNWallet, useWallet } from "Wallet";
|
import { LNWallet, useWallet } from "@/Wallet";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
import { ZapTarget, ZapTargetResult, Zapper } from "Zapper";
|
import { ZapTarget, ZapTargetResult, Zapper } from "@/Zapper";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<p className="flex g12">
|
<p className="flex g12">
|
||||||
<Icon name="check" className="success" />
|
<Icon name="check" className="success" />
|
||||||
{success?.description ?? <FormattedMessage defaultMessage="Paid" />}
|
{success?.description ?? <FormattedMessage defaultMessage="Paid" id="u/vOPu" />}
|
||||||
</p>
|
</p>
|
||||||
{success.url && (
|
{success.url && (
|
||||||
<p>
|
<p>
|
||||||
@ -123,9 +123,9 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
<>
|
<>
|
||||||
<h2>
|
<h2>
|
||||||
{zapper?.canZap() ? (
|
{zapper?.canZap() ? (
|
||||||
<FormattedMessage defaultMessage="Send zap" />
|
<FormattedMessage defaultMessage="Send zap" id="5ykRmX" />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage defaultMessage="Send sats" />
|
<FormattedMessage defaultMessage="Send sats" id="DKnriN" />
|
||||||
)}
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
</>
|
</>
|
||||||
@ -141,9 +141,9 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
{t.zap?.pubkey && <ProfileImage pubkey={t.zap.pubkey} showUsername={false} />}
|
{t.zap?.pubkey && <ProfileImage pubkey={t.zap.pubkey} showUsername={false} />}
|
||||||
<h2>
|
<h2>
|
||||||
{zapper?.canZap() ? (
|
{zapper?.canZap() ? (
|
||||||
<FormattedMessage defaultMessage="Send zap to {name}" values={values} />
|
<FormattedMessage defaultMessage="Send zap to {name}" id="SMO+on" values={values} />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage defaultMessage="Send sats to {name}" values={values} />
|
<FormattedMessage defaultMessage="Send sats to {name}" id="JGrt9q" values={values} />
|
||||||
)}
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
</>
|
</>
|
||||||
@ -156,9 +156,9 @@ export default function SendSats(props: SendSatsProps) {
|
|||||||
<div className="flex flex-col g12">
|
<div className="flex flex-col g12">
|
||||||
<h2>
|
<h2>
|
||||||
{zapper?.canZap() ? (
|
{zapper?.canZap() ? (
|
||||||
<FormattedMessage defaultMessage="Send zap splits to" />
|
<FormattedMessage defaultMessage="Send zap splits to" id="ZS+jRE" />
|
||||||
) : (
|
) : (
|
||||||
<FormattedMessage defaultMessage="Send sats splits to" />
|
<FormattedMessage defaultMessage="Send sats splits to" id="uc0din" />
|
||||||
)}
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex g4 f-wrap">
|
<div className="flex g4 f-wrap">
|
||||||
@ -330,7 +330,7 @@ function SendSatsInput(props: {
|
|||||||
<div className="flex flex-col g24">
|
<div className="flex flex-col g24">
|
||||||
<div className="flex flex-col g8">
|
<div className="flex flex-col g8">
|
||||||
<h3>
|
<h3>
|
||||||
<FormattedMessage defaultMessage="Zap amount in sats" />
|
<FormattedMessage defaultMessage="Zap amount in sats" id="zcaOTs" />
|
||||||
</h3>
|
</h3>
|
||||||
{renderAmounts()}
|
{renderAmounts()}
|
||||||
{custom()}
|
{custom()}
|
||||||
@ -348,7 +348,7 @@ function SendSatsInput(props: {
|
|||||||
{(amount ?? 0) > 0 && (
|
{(amount ?? 0) > 0 && (
|
||||||
<AsyncButton onClick={() => props.onNextStage(getValue())}>
|
<AsyncButton onClick={() => props.onNextStage(getValue())}>
|
||||||
<Icon name="zap" />
|
<Icon name="zap" />
|
||||||
<FormattedMessage defaultMessage="Zap {n} sats" values={{ n: formatShort(amount) }} />
|
<FormattedMessage defaultMessage="Zap {n} sats" id="8QDesP" values={{ n: formatShort(amount) }} />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -365,15 +365,15 @@ function SendSatsZapTypeSelector({ zapType, setZapType }: { zapType: ZapType; se
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col g8">
|
<div className="flex flex-col g8">
|
||||||
<h3>
|
<h3>
|
||||||
<FormattedMessage defaultMessage="Zap Type" />
|
<FormattedMessage defaultMessage="Zap Type" id="+aZY2h" />
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex g8">
|
<div className="flex g8">
|
||||||
{!readonly && makeTab(ZapType.PublicZap, <FormattedMessage defaultMessage="Public" description="Public Zap" />)}
|
{!readonly && makeTab(ZapType.PublicZap, <FormattedMessage defaultMessage="Public" id="/PCavi" description="Public Zap" />)}
|
||||||
{/*makeTab(ZapType.PrivateZap, "Private")*/}
|
{/*makeTab(ZapType.PrivateZap, "Private")*/}
|
||||||
{makeTab(ZapType.AnonZap, <FormattedMessage defaultMessage="Anon" description="Anonymous Zap" />)}
|
{makeTab(ZapType.AnonZap, <FormattedMessage defaultMessage="Anon" id="wWLwvh" description="Anonymous Zap" />)}
|
||||||
{makeTab(
|
{makeTab(
|
||||||
ZapType.NonZap,
|
ZapType.NonZap,
|
||||||
<FormattedMessage defaultMessage="Non-Zap" description="Non-Zap, Regular LN payment" />,
|
<FormattedMessage defaultMessage="Non-Zap" id="AnLrRC" description="Non-Zap, Regular LN payment" />,
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -396,7 +396,7 @@ function SendSatsInvoice(props: {
|
|||||||
<Copy text={v.pr} maxSize={26} className="items-center" />
|
<Copy text={v.pr} maxSize={26} className="items-center" />
|
||||||
<a href={`lightning:${v.pr}`}>
|
<a href={`lightning:${v.pr}`}>
|
||||||
<button type="button">
|
<button type="button">
|
||||||
<FormattedMessage defaultMessage="Open Wallet" />
|
<FormattedMessage defaultMessage="Open Wallet" id="HbefNb" />
|
||||||
</button>
|
</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import "./SpotlightMedia.css";
|
import "./SpotlightMedia.css";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { ProxyImg } from "Element/ProxyImg";
|
import { ProxyImg } from "@/Element/ProxyImg";
|
||||||
|
|
||||||
interface SpotlightMediaProps {
|
interface SpotlightMediaProps {
|
||||||
images: Array<string>;
|
images: Array<string>;
|
||||||
|
@ -2,12 +2,12 @@ import { useEffect, useState } from "react";
|
|||||||
import { HexKey, NostrPrefix } from "@snort/system";
|
import { HexKey, NostrPrefix } from "@snort/system";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import FollowListBase from "Element/User/FollowListBase";
|
import FollowListBase from "@/Element/User/FollowListBase";
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
import NostrBandApi from "External/NostrBand";
|
import NostrBandApi from "@/External/NostrBand";
|
||||||
import SemisolDevApi from "External/SemisolDev";
|
import SemisolDevApi from "@/External/SemisolDev";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { hexToBech32 } from "SnortUtils";
|
import { hexToBech32 } from "@/SnortUtils";
|
||||||
import { ErrorOrOffline } from "./ErrorOrOffline";
|
import { ErrorOrOffline } from "./ErrorOrOffline";
|
||||||
|
|
||||||
enum Provider {
|
enum Provider {
|
||||||
@ -57,7 +57,7 @@ export default function SuggestedProfiles() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-between bg-superdark p br">
|
<div className="flex items-center justify-between bg-superdark p br">
|
||||||
<FormattedMessage defaultMessage="Provider" />
|
<FormattedMessage defaultMessage="Provider" id="xaj9Ba" />
|
||||||
<select onChange={e => setProvider(Number(e.target.value))}>
|
<select onChange={e => setProvider(Number(e.target.value))}>
|
||||||
<option value={Provider.NostrBand}>nostr.band</option>
|
<option value={Provider.NostrBand}>nostr.band</option>
|
||||||
{/*<option value={Provider.SemisolDev}>semisol.dev</option>*/}
|
{/*<option value={Provider.SemisolDev}>semisol.dev</option>*/}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import "./Tabs.css";
|
import "./Tabs.css";
|
||||||
import useHorizontalScroll from "Hooks/useHorizontalScroll";
|
import useHorizontalScroll from "@/Hooks/useHorizontalScroll";
|
||||||
|
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
text: ReactNode;
|
text: ReactNode;
|
||||||
|
@ -3,15 +3,15 @@ import { ReactNode, useState } from "react";
|
|||||||
import { HexKey, ParsedFragment } from "@snort/system";
|
import { HexKey, ParsedFragment } from "@snort/system";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import Invoice from "Element/Embed/Invoice";
|
import Invoice from "@/Element/Embed/Invoice";
|
||||||
import Hashtag from "Element/Embed/Hashtag";
|
import Hashtag from "@/Element/Embed/Hashtag";
|
||||||
import HyperText from "Element/HyperText";
|
import HyperText from "@/Element/HyperText";
|
||||||
import CashuNuts from "Element/Embed/CashuNuts";
|
import CashuNuts from "@/Element/Embed/CashuNuts";
|
||||||
import RevealMedia from "./Event/RevealMedia";
|
import RevealMedia from "./Event/RevealMedia";
|
||||||
import { ProxyImg } from "./ProxyImg";
|
import { ProxyImg } from "./ProxyImg";
|
||||||
import { SpotlightMediaModal } from "./SpotlightMedia";
|
import { SpotlightMediaModal } from "./SpotlightMedia";
|
||||||
import HighlightedText from "./HighlightedText";
|
import HighlightedText from "./HighlightedText";
|
||||||
import { useTextTransformer } from "Hooks/useTextTransformCache";
|
import { useTextTransformer } from "@/Hooks/useTextTransformCache";
|
||||||
|
|
||||||
export interface TextProps {
|
export interface TextProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -6,11 +6,11 @@ import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
|
|||||||
import TextareaAutosize from "react-textarea-autosize";
|
import TextareaAutosize from "react-textarea-autosize";
|
||||||
import { NostrPrefix, MetadataCache } from "@snort/system";
|
import { NostrPrefix, MetadataCache } from "@snort/system";
|
||||||
|
|
||||||
import Avatar from "Element/User/Avatar";
|
import Avatar from "@/Element/User/Avatar";
|
||||||
import Nip05 from "Element/User/Nip05";
|
import Nip05 from "@/Element/User/Nip05";
|
||||||
import { hexToBech32 } from "SnortUtils";
|
import { hexToBech32 } from "@/SnortUtils";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
import searchEmoji from "emoji-search";
|
import searchEmoji from "@/emoji-search";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
|
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
import NostrBandApi from "External/NostrBand";
|
import NostrBandApi from "@/External/NostrBand";
|
||||||
import { ErrorOrOffline } from "./ErrorOrOffline";
|
import { ErrorOrOffline } from "./ErrorOrOffline";
|
||||||
import { HashTagHeader } from "Pages/HashTagsPage";
|
import { HashTagHeader } from "@/Pages/HashTagsPage";
|
||||||
import { useLocale } from "IntlProvider";
|
import { useLocale } from "@/IntlProvider";
|
||||||
|
|
||||||
export default function TrendingHashtags({ title }: { title?: ReactNode }) {
|
export default function TrendingHashtags({ title }: { title?: ReactNode }) {
|
||||||
const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>();
|
const [hashtags, setHashtags] = useState<Array<{ hashtag: string; posts: number }>>();
|
||||||
|
@ -2,12 +2,12 @@ import { useEffect, useState } from "react";
|
|||||||
import { NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/system";
|
import { NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/system";
|
||||||
import { useReactions } from "@snort/system-react";
|
import { useReactions } from "@snort/system-react";
|
||||||
|
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import NostrBandApi from "External/NostrBand";
|
import NostrBandApi from "@/External/NostrBand";
|
||||||
import { ErrorOrOffline } from "Element/ErrorOrOffline";
|
import { ErrorOrOffline } from "@/Element/ErrorOrOffline";
|
||||||
import { useLocale } from "IntlProvider";
|
import { useLocale } from "@/IntlProvider";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
|
|
||||||
export default function TrendingNotes() {
|
export default function TrendingNotes() {
|
||||||
const [posts, setPosts] = useState<Array<NostrEvent>>();
|
const [posts, setPosts] = useState<Array<NostrEvent>>();
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
|
|
||||||
import FollowListBase from "Element/User/FollowListBase";
|
import FollowListBase from "@/Element/User/FollowListBase";
|
||||||
import PageSpinner from "Element/PageSpinner";
|
import PageSpinner from "@/Element/PageSpinner";
|
||||||
import NostrBandApi from "External/NostrBand";
|
import NostrBandApi from "@/External/NostrBand";
|
||||||
import { ErrorOrOffline } from "./ErrorOrOffline";
|
import { ErrorOrOffline } from "./ErrorOrOffline";
|
||||||
|
|
||||||
export default function TrendingUsers({ title }: { title?: ReactNode }) {
|
export default function TrendingUsers({ title }: { title?: ReactNode }) {
|
||||||
|
@ -4,8 +4,8 @@ import { CSSProperties, ReactNode, useEffect, useState } from "react";
|
|||||||
import type { UserMetadata } from "@snort/system";
|
import type { UserMetadata } from "@snort/system";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import useImgProxy from "Hooks/useImgProxy";
|
import useImgProxy from "@/Hooks/useImgProxy";
|
||||||
import { defaultAvatar, getDisplayName } from "SnortUtils";
|
import { defaultAvatar, getDisplayName } from "@/SnortUtils";
|
||||||
|
|
||||||
interface AvatarProps {
|
interface AvatarProps {
|
||||||
pubkey: string;
|
pubkey: string;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import "./AvatarEditor.css";
|
import "./AvatarEditor.css";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import useFileUpload from "Upload";
|
import useFileUpload from "@/Upload";
|
||||||
import { openFile, unwrap } from "SnortUtils";
|
import { openFile, unwrap } from "@/SnortUtils";
|
||||||
import Spinner from "Icons/Spinner";
|
import Spinner from "@/Icons/Spinner";
|
||||||
|
|
||||||
interface AvatarEditorProps {
|
interface AvatarEditorProps {
|
||||||
picture?: string;
|
picture?: string;
|
||||||
|
@ -5,11 +5,11 @@ import { FormattedMessage } from "react-intl";
|
|||||||
|
|
||||||
import { TaggedNostrEvent } from "@snort/system";
|
import { TaggedNostrEvent } from "@snort/system";
|
||||||
|
|
||||||
import { ProxyImg } from "Element/ProxyImg";
|
import { ProxyImg } from "@/Element/ProxyImg";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import Modal from "Element/Modal";
|
import Modal from "@/Element/Modal";
|
||||||
import Username from "Element/User/Username";
|
import Username from "@/Element/User/Username";
|
||||||
import { findTag } from "SnortUtils";
|
import { findTag } from "@/SnortUtils";
|
||||||
|
|
||||||
export default function BadgeList({ badges }: { badges: TaggedNostrEvent[] }) {
|
export default function BadgeList({ badges }: { badges: TaggedNostrEvent[] }) {
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
@ -42,7 +42,7 @@ export default function BadgeList({ badges }: { badges: TaggedNostrEvent[] }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="reactions-header">
|
<div className="reactions-header">
|
||||||
<h2>
|
<h2>
|
||||||
<FormattedMessage defaultMessage="Badges" />
|
<FormattedMessage defaultMessage="Badges" id="h8XMJL" />
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="body">
|
<div className="body">
|
||||||
@ -55,7 +55,7 @@ export default function BadgeList({ badges }: { badges: TaggedNostrEvent[] }) {
|
|||||||
<p>{description}</p>
|
<p>{description}</p>
|
||||||
<p>
|
<p>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="By: {author}"
|
defaultMessage="By: {author}" id="RfhLwC"
|
||||||
values={{ author: <Username pubkey={pubkey} onLinkVisit={() => setShowModal(false)} /> }}
|
values={{ author: <Username pubkey={pubkey} onLinkVisit={() => setShowModal(false)} /> }}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import BlockButton from "Element/User/BlockButton";
|
import BlockButton from "@/Element/User/BlockButton";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "@/Element/User/ProfilePreview";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
|
|
||||||
export default function BlockList() {
|
export default function BlockList() {
|
||||||
const { blocked } = useModeration();
|
const { blocked } = useModeration();
|
||||||
|
@ -2,9 +2,9 @@ import { useState, useMemo, ChangeEvent } from "react";
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { HexKey, TaggedNostrEvent } from "@snort/system";
|
import { HexKey, TaggedNostrEvent } from "@snort/system";
|
||||||
|
|
||||||
import Note from "Element/Event/Note";
|
import Note from "@/Element/Event/Note";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { UserCache } from "Cache";
|
import { UserCache } from "@/Cache";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import "./DisplayName.css";
|
|||||||
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { HexKey, UserMetadata } from "@snort/system";
|
import { HexKey, UserMetadata } from "@snort/system";
|
||||||
import { getDisplayNameOrPlaceHolder } from "SnortUtils";
|
import { getDisplayNameOrPlaceHolder } from "@/SnortUtils";
|
||||||
|
|
||||||
interface DisplayNameProps {
|
interface DisplayNameProps {
|
||||||
pubkey: HexKey;
|
pubkey: HexKey;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import { parseId } from "SnortUtils";
|
import { parseId } from "@/SnortUtils";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import AsyncButton from "Element/AsyncButton";
|
import AsyncButton from "@/Element/AsyncButton";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { FollowsFeed } from "Cache";
|
import { FollowsFeed } from "@/Cache";
|
||||||
|
|
||||||
export interface FollowButtonProps {
|
export interface FollowButtonProps {
|
||||||
pubkey: HexKey;
|
pubkey: HexKey;
|
||||||
|
@ -3,14 +3,14 @@ import { FormattedMessage } from "react-intl";
|
|||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import { dedupe } from "@snort/shared";
|
import { dedupe } from "@snort/shared";
|
||||||
|
|
||||||
import useEventPublisher from "Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "@/Element/User/ProfilePreview";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
import { FollowsFeed } from "Cache";
|
import { FollowsFeed } from "@/Cache";
|
||||||
import AsyncButton from "../AsyncButton";
|
import AsyncButton from "../AsyncButton";
|
||||||
import { setFollows } from "Login";
|
import { setFollows } from "@/Login";
|
||||||
|
|
||||||
export interface FollowListBaseProps {
|
export interface FollowListBaseProps {
|
||||||
pubkeys: HexKey[];
|
pubkeys: HexKey[];
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import "./Following.css";
|
import "./Following.css";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
|
|
||||||
export function FollowingMark({ pubkey }: { pubkey: string }) {
|
export function FollowingMark({ pubkey }: { pubkey: string }) {
|
||||||
const { follows } = useLogin(s => ({ follows: s.follows }));
|
const { follows } = useLogin(s => ({ follows: s.follows }));
|
||||||
@ -12,7 +12,7 @@ export function FollowingMark({ pubkey }: { pubkey: string }) {
|
|||||||
return (
|
return (
|
||||||
<span className="following flex g4">
|
<span className="following flex g4">
|
||||||
<Icon name="check" className="success" size={12} />
|
<Icon name="check" className="success" size={12} />
|
||||||
<FormattedMessage defaultMessage="following" />
|
<FormattedMessage defaultMessage="following" id="+tShPg" />
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
import { HexKey } from "@snort/system";
|
import { HexKey } from "@snort/system";
|
||||||
import MuteButton from "Element/User/MuteButton";
|
import MuteButton from "@/Element/User/MuteButton";
|
||||||
import ProfilePreview from "Element/User/ProfilePreview";
|
import ProfilePreview from "@/Element/User/ProfilePreview";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
|
|
||||||
import messages from "../messages";
|
import messages from "../messages";
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user