feat: translations
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { HexKey, RawEvent } from "Nostr";
|
||||
@ -10,6 +11,8 @@ import { RootState } from "State/Store";
|
||||
import NoteToSelf from "Element/NoteToSelf";
|
||||
import useModeration from "Hooks/useModeration";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
type DmChat = {
|
||||
pubkey: HexKey;
|
||||
unreadMessages: number;
|
||||
@ -71,9 +74,11 @@ export default function MessagesPage() {
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="flex">
|
||||
<h3 className="f-grow">Messages</h3>
|
||||
<h3 className="f-grow">
|
||||
<FormattedMessage {...messages.Messages} />
|
||||
</h3>
|
||||
<button type="button" onClick={() => markAllRead()}>
|
||||
Mark All Read
|
||||
<FormattedMessage {...messages.MarkAllRead} />
|
||||
</button>
|
||||
</div>
|
||||
{chats
|
||||
|
@ -1,6 +1,6 @@
|
||||
import "./ProfilePage.css";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useIntl, FormattedMessage } from "react-intl";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
|
||||
@ -37,17 +37,18 @@ import Modal from "Element/Modal";
|
||||
import { ProxyImg } from "Element/ProxyImg";
|
||||
import useHorizontalScroll from "Hooks/useHorizontalScroll";
|
||||
|
||||
const ProfileTab = {
|
||||
Notes: { text: "Notes", value: 0 },
|
||||
Reactions: { text: "Reactions", value: 1 },
|
||||
Followers: { text: "Followers", value: 2 },
|
||||
Follows: { text: "Follows", value: 3 },
|
||||
Zaps: { text: "Zaps", value: 4 },
|
||||
Muted: { text: "Muted", value: 5 },
|
||||
Blocked: { text: "Blocked", value: 6 },
|
||||
};
|
||||
import messages from "./messages";
|
||||
|
||||
const NOTES = 0;
|
||||
const REACTIONS = 1;
|
||||
const FOLLOWERS = 2;
|
||||
const FOLLOWS = 3;
|
||||
const ZAPS = 4;
|
||||
const MUTED = 5;
|
||||
const BLOCKED = 6;
|
||||
|
||||
export default function ProfilePage() {
|
||||
const { formatMessage } = useIntl();
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const id = useMemo(() => parseId(params.id!), [params]);
|
||||
@ -61,7 +62,6 @@ export default function ProfilePage() {
|
||||
const follows = useSelector<RootState, HexKey[]>((s) => s.login.follows);
|
||||
const isMe = loginPubKey === id;
|
||||
const [showLnQr, setShowLnQr] = useState<boolean>(false);
|
||||
const [tab, setTab] = useState<Tab>(ProfileTab.Notes);
|
||||
const [showProfileQr, setShowProfileQr] = useState<boolean>(false);
|
||||
const aboutText = user?.about || "";
|
||||
const about = Text({
|
||||
@ -85,6 +85,16 @@ export default function ProfilePage() {
|
||||
}, [zapFeed.store, id]);
|
||||
const zapsTotal = zaps.reduce((acc, z) => acc + z.amount, 0);
|
||||
const horizontalScroll = useHorizontalScroll();
|
||||
const ProfileTab = {
|
||||
Notes: { text: formatMessage(messages.Notes), value: NOTES },
|
||||
Reactions: { text: formatMessage(messages.Reactions), value: REACTIONS },
|
||||
Followers: { text: formatMessage(messages.Followers), value: FOLLOWERS },
|
||||
Follows: { text: formatMessage(messages.Follows), value: FOLLOWS },
|
||||
Zaps: { text: formatMessage(messages.Zaps), value: ZAPS },
|
||||
Muted: { text: formatMessage(messages.Muted), value: MUTED },
|
||||
Blocked: { text: formatMessage(messages.Blocked), value: BLOCKED },
|
||||
};
|
||||
const [tab, setTab] = useState<Tab>(ProfileTab.Notes);
|
||||
|
||||
useEffect(() => {
|
||||
setTab(ProfileTab.Notes);
|
||||
@ -149,8 +159,8 @@ export default function ProfilePage() {
|
||||
}
|
||||
|
||||
function tabContent() {
|
||||
switch (tab) {
|
||||
case ProfileTab.Notes:
|
||||
switch (tab.value) {
|
||||
case NOTES:
|
||||
return (
|
||||
<Timeline
|
||||
key={id}
|
||||
@ -164,10 +174,15 @@ export default function ProfilePage() {
|
||||
ignoreModeration={true}
|
||||
/>
|
||||
);
|
||||
case ProfileTab.Zaps: {
|
||||
case ZAPS: {
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h4 className="zaps-total">{formatShort(zapsTotal)} sats</h4>
|
||||
<h4 className="zaps-total">
|
||||
<FormattedMessage
|
||||
{...messages.Sats}
|
||||
values={{ n: formatShort(zapsTotal) }}
|
||||
/>
|
||||
</h4>
|
||||
{zaps.map((z) => (
|
||||
<ZapElement showZapped={false} zap={z} />
|
||||
))}
|
||||
@ -175,11 +190,16 @@ export default function ProfilePage() {
|
||||
);
|
||||
}
|
||||
|
||||
case ProfileTab.Follows: {
|
||||
case FOLLOWS: {
|
||||
if (isMe) {
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h4>Following {follows.length}</h4>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
{...messages.Following}
|
||||
values={{ n: follows.length }}
|
||||
/>
|
||||
</h4>
|
||||
{follows.map((a) => (
|
||||
<ProfilePreview
|
||||
key={a}
|
||||
@ -193,13 +213,13 @@ export default function ProfilePage() {
|
||||
return <FollowsList pubkey={id} />;
|
||||
}
|
||||
}
|
||||
case ProfileTab.Followers: {
|
||||
case FOLLOWERS: {
|
||||
return <FollowersList pubkey={id} />;
|
||||
}
|
||||
case ProfileTab.Muted: {
|
||||
case MUTED: {
|
||||
return isMe ? <BlockList variant="muted" /> : <MutedList pubkey={id} />;
|
||||
}
|
||||
case ProfileTab.Blocked: {
|
||||
case BLOCKED: {
|
||||
return isMe ? <BlockList variant="blocked" /> : null;
|
||||
}
|
||||
}
|
||||
@ -233,7 +253,7 @@ export default function ProfilePage() {
|
||||
<>
|
||||
<LogoutButton />
|
||||
<button type="button" onClick={() => navigate("/settings")}>
|
||||
Settings
|
||||
<FormattedMessage {...messages.Settings} />
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
|
@ -2,6 +2,7 @@ import "./Root.css";
|
||||
import { useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import Tabs, { Tab } from "Element/Tabs";
|
||||
import { RootState } from "State/Store";
|
||||
@ -9,10 +10,21 @@ import Timeline from "Element/Timeline";
|
||||
import { HexKey } from "Nostr";
|
||||
import { TimelineSubject } from "Feed/TimelineFeed";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const RootTab: Record<string, Tab> = {
|
||||
Posts: { text: "Posts", value: 0 },
|
||||
PostsAndReplies: { text: "Conversations", value: 1 },
|
||||
Global: { text: "Global", value: 2 },
|
||||
Posts: {
|
||||
text: <FormattedMessage {...messages.Posts} />,
|
||||
value: 0,
|
||||
},
|
||||
PostsAndReplies: {
|
||||
text: <FormattedMessage {...messages.Conversations} />,
|
||||
value: 1,
|
||||
},
|
||||
Global: {
|
||||
text: <FormattedMessage {...messages.Global} />,
|
||||
value: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootPage() {
|
||||
@ -25,10 +37,16 @@ export default function RootPage() {
|
||||
function followHints() {
|
||||
if (follows?.length === 0 && pubKey && tab !== RootTab.Global) {
|
||||
return (
|
||||
<>
|
||||
Hmm nothing here.. Checkout <Link to={"/new"}>New users page</Link> to
|
||||
follow some recommended nostrich's!
|
||||
</>
|
||||
<FormattedMessage
|
||||
{...messages.NoFollows}
|
||||
values={{
|
||||
newUsersPage: (
|
||||
<Link to={"/new"}>
|
||||
<FormattedMessage {...messages.NewUsers} />
|
||||
</Link>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useIntl, FormattedMessage } from "react-intl";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Timeline from "Element/Timeline";
|
||||
import { useEffect, useState } from "react";
|
||||
@ -6,8 +7,11 @@ import { router } from "index";
|
||||
import { SearchRelays } from "Const";
|
||||
import { System } from "Nostr/System";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const SearchPage = () => {
|
||||
const params: any = useParams();
|
||||
const { formatMessage } = useIntl();
|
||||
const [search, setSearch] = useState<string>();
|
||||
const [keyword, setKeyword] = useState<string | undefined>(params.keyword);
|
||||
|
||||
@ -39,12 +43,14 @@ const SearchPage = () => {
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h2>Search</h2>
|
||||
<h2>
|
||||
<FormattedMessage {...messages.Search} />
|
||||
</h2>
|
||||
<div className="flex mb10">
|
||||
<input
|
||||
type="text"
|
||||
className="f-grow mr10"
|
||||
placeholder="Search.."
|
||||
placeholder={formatMessage(messages.SearchPlaceholder)}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Outlet, RouteObject, useNavigate } from "react-router-dom";
|
||||
import SettingsIndex from "Pages/settings/Index";
|
||||
import Profile from "Pages/settings/Profile";
|
||||
@ -5,13 +6,15 @@ import Relay from "Pages/settings/Relays";
|
||||
import Preferences from "Pages/settings/Preferences";
|
||||
import RelayInfo from "Pages/settings/RelayInfo";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export default function SettingsPage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<h2 onClick={() => navigate("/settings")} className="pointer">
|
||||
Settings
|
||||
<FormattedMessage {...messages.Settings} />
|
||||
</h2>
|
||||
<Outlet />
|
||||
</div>
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { ApiHost } from "Const";
|
||||
import Nip5Service from "Element/Nip5Service";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
import "./Verification.css";
|
||||
|
||||
export default function VerificationPage() {
|
||||
@ -10,42 +14,37 @@ export default function VerificationPage() {
|
||||
service: `${ApiHost}/api/v1/n5sp`,
|
||||
link: "https://snort.social/",
|
||||
supportLink: "https://snort.social/help",
|
||||
about: (
|
||||
<>
|
||||
Our very own NIP-05 verification service, help support the development
|
||||
of this site and get a shiny special badge on our site!
|
||||
</>
|
||||
),
|
||||
about: <FormattedMessage {...messages.SnortSocialNip} />,
|
||||
},
|
||||
{
|
||||
name: "Nostr Plebs",
|
||||
service: "https://nostrplebs.com/api/v1",
|
||||
link: "https://nostrplebs.com/",
|
||||
supportLink: "https://nostrplebs.com/manage",
|
||||
about: (
|
||||
<>
|
||||
<p>
|
||||
Nostr Plebs is one of the first NIP-05 providers in the space and
|
||||
offers a good collection of domains at reasonable prices
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
about: <FormattedMessage {...messages.NostrPlebsNip} />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="main-content verification">
|
||||
<h2>Get Verified</h2>
|
||||
<h2>
|
||||
<FormattedMessage {...messages.GetVerified} />
|
||||
</h2>
|
||||
<p>
|
||||
NIP-05 is a DNS based verification spec which helps to validate you as a
|
||||
real user.
|
||||
<FormattedMessage {...messages.Nip05} />
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage {...messages.Nip05Pros} />
|
||||
</p>
|
||||
<p>Getting NIP-05 verified can help:</p>
|
||||
<ul>
|
||||
<li>Prevent fake accounts from imitating you</li>
|
||||
<li>Make your profile easier to find and share</li>
|
||||
<li>
|
||||
Fund developers and platforms providing NIP-05 verification services
|
||||
<FormattedMessage {...messages.AvoidImpersonators} />
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage {...messages.EasierToFind} />
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage {...messages.Funding} />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -3,6 +3,35 @@ import { addIdAndDefaultMessageToMessages } from "Util";
|
||||
|
||||
const messages = defineMessages({
|
||||
Login: "Login",
|
||||
Posts: "Posts",
|
||||
Conversations: "Conversations",
|
||||
Global: "Global",
|
||||
NewUsers: "New users page",
|
||||
NoFollows:
|
||||
"Hmm nothing here.. Checkout {newUsersPage} to follow some recommended nostrich's!",
|
||||
Notes: "Notes",
|
||||
Reactions: "Reactions",
|
||||
Followers: "Followers",
|
||||
Follows: "Follows",
|
||||
Zaps: "Zaps",
|
||||
Muted: "Muted",
|
||||
Blocked: "Blocked",
|
||||
Sats: "{n} {n, plural, =1 {sat} other {sats}}",
|
||||
Following: "Following {n}",
|
||||
Settings: "Settings",
|
||||
Search: "Search",
|
||||
SearchPlaceholder: "Search...",
|
||||
Messages: "Messages",
|
||||
MarkAllRead: "Mark All Read",
|
||||
GetVerified: "Get Verified",
|
||||
Nip05: `NIP-05 is a DNS based verification spec which helps to validate you as a real user.`,
|
||||
Nip05Pros: `Getting NIP-05 verified can help:`,
|
||||
AvoidImpersonators: "Prevent fake accounts from imitating you",
|
||||
EasierToFind: "Make your profile easier to find and share",
|
||||
Funding:
|
||||
"Fund developers and platforms providing NIP-05 verification services",
|
||||
SnortSocialNip: `Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!`,
|
||||
NostrPlebsNip: `Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices`,
|
||||
});
|
||||
|
||||
export default addIdAndDefaultMessageToMessages(messages, 'Pages');
|
||||
export default addIdAndDefaultMessageToMessages(messages, "Pages");
|
||||
|
@ -1,5 +1,5 @@
|
||||
import "./Index.css";
|
||||
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import ArrowFront from "Icons/ArrowFront";
|
||||
@ -8,9 +8,10 @@ import Profile from "Icons/Profile";
|
||||
import Relay from "Icons/Relay";
|
||||
import Heart from "Icons/Heart";
|
||||
import Logout from "Icons/Logout";
|
||||
|
||||
import { logout } from "State/Login";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const SettingsIndex = () => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
@ -27,7 +28,9 @@ const SettingsIndex = () => {
|
||||
<div className="mr10">
|
||||
<Profile />
|
||||
</div>
|
||||
<span>Profile</span>
|
||||
<span>
|
||||
<FormattedMessage {...messages.Profile} />
|
||||
</span>
|
||||
<div className="align-end">
|
||||
<ArrowFront />
|
||||
</div>
|
||||
@ -36,7 +39,7 @@ const SettingsIndex = () => {
|
||||
<div className="mr10">
|
||||
<Relay />
|
||||
</div>
|
||||
Relays
|
||||
<FormattedMessage {...messages.Relays} />
|
||||
<div className="align-end">
|
||||
<ArrowFront />
|
||||
</div>
|
||||
@ -45,7 +48,7 @@ const SettingsIndex = () => {
|
||||
<div className="mr10">
|
||||
<Gear />
|
||||
</div>
|
||||
Preferences
|
||||
<FormattedMessage {...messages.Preferences} />
|
||||
<div className="align-end">
|
||||
<ArrowFront />
|
||||
</div>
|
||||
@ -63,7 +66,7 @@ const SettingsIndex = () => {
|
||||
<div className="mr10">
|
||||
<Logout />
|
||||
</div>
|
||||
Log Out
|
||||
<FormattedMessage {...messages.LogOut} />
|
||||
<div className="align-end">
|
||||
<ArrowFront />
|
||||
</div>
|
||||
|
@ -1,7 +1,12 @@
|
||||
import "./Preferences.css";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import { DefaultImgProxy, setPreferences, UserPreferences } from "State/Login";
|
||||
import { RootState } from "State/Store";
|
||||
import "./Preferences.css";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const PreferencesPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
@ -11,11 +16,15 @@ const PreferencesPage = () => {
|
||||
|
||||
return (
|
||||
<div className="preferences">
|
||||
<h3>Preferences</h3>
|
||||
<h3>
|
||||
<FormattedMessage {...messages.Preferences} />
|
||||
</h3>
|
||||
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Theme</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.Theme} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<select
|
||||
@ -29,18 +38,25 @@ const PreferencesPage = () => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="system">System (Default)</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="system">
|
||||
<FormattedMessage {...messages.System} />
|
||||
</option>
|
||||
<option value="light">
|
||||
<FormattedMessage {...messages.Light} />
|
||||
</option>
|
||||
<option value="dark">
|
||||
<FormattedMessage {...messages.Dark} />
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Automatically load media</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.AutoloadMedia} />
|
||||
</div>
|
||||
<small>
|
||||
Media in posts will automatically be shown for selected people,
|
||||
otherwise only the link will show
|
||||
<FormattedMessage {...messages.AutoloadMediaHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
@ -55,17 +71,27 @@ const PreferencesPage = () => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="none">None</option>
|
||||
<option value="follows-only">Follows only</option>
|
||||
<option value="all">All</option>
|
||||
<option value="none">
|
||||
<FormattedMessage {...messages.None} />
|
||||
</option>
|
||||
<option value="follows-only">
|
||||
<FormattedMessage {...messages.FollowsOnly} />
|
||||
</option>
|
||||
<option value="all">
|
||||
<FormattedMessage {...messages.All} />
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card flex f-col">
|
||||
<div className="flex w-max">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Image proxy service</div>
|
||||
<small>Use imgproxy to compress images</small>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ImgProxy} />
|
||||
</div>
|
||||
<small>
|
||||
<FormattedMessage {...messages.ImgProxyHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
@ -85,12 +111,14 @@ const PreferencesPage = () => {
|
||||
{perf.imgProxyConfig && (
|
||||
<div className="w-max mt10 form">
|
||||
<div className="form-group">
|
||||
<div>Service Url</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ServiceUrl} />
|
||||
</div>
|
||||
<div className="w-max">
|
||||
<input
|
||||
type="text"
|
||||
value={perf.imgProxyConfig?.url}
|
||||
placeholder="Url.."
|
||||
placeholder="URL.."
|
||||
onChange={(e) =>
|
||||
dispatch(
|
||||
setPreferences({
|
||||
@ -106,7 +134,9 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>Service Key</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ServiceKey} />
|
||||
</div>
|
||||
<div className="w-max">
|
||||
<input
|
||||
type="password"
|
||||
@ -127,7 +157,9 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>Service Salt</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ServiceSalt} />
|
||||
</div>
|
||||
<div className="w-max">
|
||||
<input
|
||||
type="password"
|
||||
@ -152,10 +184,11 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Enable reactions</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.EnableReactions} />
|
||||
</div>
|
||||
<small>
|
||||
Reactions will be shown on every page, if disabled no reactions will
|
||||
be shown
|
||||
<FormattedMessage {...messages.EnableReactionsHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
@ -172,8 +205,12 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Confirm reposts</div>
|
||||
<small>Reposts need to be manually confirmed</small>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ConfirmReposts} />
|
||||
</div>
|
||||
<small>
|
||||
<FormattedMessage {...messages.ConfirmRepostsHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
@ -189,9 +226,11 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Automatically show latest notes</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.ShowLatest} />
|
||||
</div>
|
||||
<small>
|
||||
Notes will stream in real time into global and posts tab
|
||||
<FormattedMessage {...messages.ShowLatestHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
@ -208,9 +247,11 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>File upload service</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.FileUpload} />
|
||||
</div>
|
||||
<small>
|
||||
Pick which upload service you want to upload attachments to
|
||||
<FormattedMessage {...messages.FileUploadHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
@ -225,7 +266,9 @@ const PreferencesPage = () => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<option value="void.cat">void.cat (Default)</option>
|
||||
<option value="void.cat">
|
||||
void.cat <FormattedMessage {...messages.Default} />
|
||||
</option>
|
||||
<option value="nostr.build">nostr.build</option>
|
||||
<option value="nostrimg.com">nostrimg.com</option>
|
||||
</select>
|
||||
@ -233,10 +276,11 @@ const PreferencesPage = () => {
|
||||
</div>
|
||||
<div className="card flex">
|
||||
<div className="flex f-col f-grow">
|
||||
<div>Debug Menus</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.DebugMenus} />
|
||||
</div>
|
||||
<small>
|
||||
Shows "Copy ID" and "Copy Event JSON" in the context menu on each
|
||||
message
|
||||
<FormattedMessage {...messages.DebugMenusHelp} />
|
||||
</small>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import "./Profile.css";
|
||||
import Nostrich from "nostrich.webp";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
@ -15,6 +15,8 @@ import { RootState } from "State/Store";
|
||||
import { HexKey } from "Nostr";
|
||||
import useFileUpload from "Upload";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
export interface ProfileSettingsProps {
|
||||
avatar?: boolean;
|
||||
banner?: boolean;
|
||||
@ -112,7 +114,9 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
return (
|
||||
<div className="editor form">
|
||||
<div className="form-group">
|
||||
<div>Name:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.Name} />:
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
@ -122,7 +126,9 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>Display name:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.DisplayName} />:
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
@ -132,7 +138,9 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group form-col">
|
||||
<div>About:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.About} />:
|
||||
</div>
|
||||
<div className="w-max">
|
||||
<textarea
|
||||
className="w-max"
|
||||
@ -142,7 +150,9 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>Website:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.Website} />:
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
@ -152,7 +162,9 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>NIP-05:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.Nip05} />:
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
@ -162,12 +174,14 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
/>
|
||||
<button type="button" onClick={() => navigate("/verification")}>
|
||||
<FontAwesomeIcon icon={faShop} />
|
||||
Buy
|
||||
<FormattedMessage {...messages.Buy} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<div>LN Address:</div>
|
||||
<div>
|
||||
<FormattedMessage {...messages.LnAddress} />:
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
@ -180,7 +194,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
<div></div>
|
||||
<div>
|
||||
<button type="button" onClick={() => saveProfile()}>
|
||||
Save
|
||||
<FormattedMessage {...messages.Save} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -195,20 +209,24 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
<div className="flex f-center image-settings">
|
||||
{(props.avatar ?? true) && (
|
||||
<div>
|
||||
<h2>Avatar</h2>
|
||||
<h2>
|
||||
<FormattedMessage {...messages.Avatar} />
|
||||
</h2>
|
||||
<div
|
||||
style={{ backgroundImage: `url(${avatarPicture})` }}
|
||||
className="avatar"
|
||||
>
|
||||
<div className="edit" onClick={() => setNewAvatar()}>
|
||||
Edit
|
||||
<FormattedMessage {...messages.Edit} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{(props.banner ?? true) && (
|
||||
<div>
|
||||
<h2>Header</h2>
|
||||
<h2>
|
||||
<FormattedMessage {...messages.Banner} />
|
||||
</h2>
|
||||
<div
|
||||
style={{
|
||||
backgroundImage: `url(${
|
||||
@ -218,7 +236,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
className="banner"
|
||||
>
|
||||
<div className="edit" onClick={() => setNewBanner()}>
|
||||
Edit
|
||||
<FormattedMessage {...messages.Edit} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -231,12 +249,16 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
|
||||
|
||||
return (
|
||||
<div className="settings">
|
||||
<h3>Edit Profile</h3>
|
||||
<h3>
|
||||
<FormattedMessage {...messages.EditProfile} />
|
||||
</h3>
|
||||
{settings()}
|
||||
{privKey && (props.privateKey ?? true) && (
|
||||
<div className="flex f-col bg-grey">
|
||||
<div>
|
||||
<h4>Your Private Key Is (do not share this with anyone):</h4>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.PrivateKey} />:
|
||||
</h4>
|
||||
</div>
|
||||
<div>
|
||||
<Copy text={hexToBech32("nsec", privKey)} />
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import ProfilePreview from "Element/ProfilePreview";
|
||||
import useRelayState from "Feed/RelayState";
|
||||
import { System } from "Nostr/System";
|
||||
@ -6,6 +7,8 @@ import { useNavigate, useParams } from "react-router-dom";
|
||||
import { removeRelay } from "State/Login";
|
||||
import { parseId } from "Util";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const RelayInfo = () => {
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
@ -20,7 +23,7 @@ const RelayInfo = () => {
|
||||
return (
|
||||
<>
|
||||
<h3 className="pointer" onClick={() => navigate("/settings/relays")}>
|
||||
Relays
|
||||
<FormattedMessage {...messages.Relays} />
|
||||
</h3>
|
||||
<div className="card">
|
||||
<h3>{stats?.info?.name}</h3>
|
||||
@ -28,13 +31,17 @@ const RelayInfo = () => {
|
||||
|
||||
{stats?.info?.pubkey && (
|
||||
<>
|
||||
<h4>Owner</h4>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.Owner} />
|
||||
</h4>
|
||||
<ProfilePreview pubkey={parseId(stats.info.pubkey)} />
|
||||
</>
|
||||
)}
|
||||
{stats?.info?.software && (
|
||||
<div className="flex">
|
||||
<h4 className="f-grow">Software</h4>
|
||||
<h4 className="f-grow">
|
||||
<FormattedMessage {...messages.Software} />
|
||||
</h4>
|
||||
<div className="flex f-col">
|
||||
{stats.info.software.startsWith("http") ? (
|
||||
<a href={stats.info.software} target="_blank" rel="noreferrer">
|
||||
@ -52,7 +59,9 @@ const RelayInfo = () => {
|
||||
)}
|
||||
{stats?.info?.contact && (
|
||||
<div className="flex">
|
||||
<h4 className="f-grow">Contact</h4>
|
||||
<h4 className="f-grow">
|
||||
<FormattedMessage {...messages.Contact} />
|
||||
</h4>
|
||||
<a
|
||||
href={`${
|
||||
stats.info.contact.startsWith("mailto:") ? "" : "mailto:"
|
||||
@ -66,7 +75,9 @@ const RelayInfo = () => {
|
||||
)}
|
||||
{stats?.info?.supported_nips && (
|
||||
<>
|
||||
<h4>Supports</h4>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.Supports} />
|
||||
</h4>
|
||||
<div className="f-grow">
|
||||
{stats.info.supported_nips.map((a) => (
|
||||
<span
|
||||
@ -93,7 +104,7 @@ const RelayInfo = () => {
|
||||
navigate("/settings/relays");
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
<FormattedMessage {...messages.Remove} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import Relay from "Element/Relay";
|
||||
@ -7,6 +8,8 @@ import { RootState } from "State/Store";
|
||||
import { RelaySettings } from "Nostr/Connection";
|
||||
import { setRelays } from "State/Login";
|
||||
|
||||
import messages from "./messages";
|
||||
|
||||
const RelaySettingsPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
const publisher = useEventPublisher();
|
||||
@ -24,7 +27,9 @@ const RelaySettingsPage = () => {
|
||||
function addRelay() {
|
||||
return (
|
||||
<>
|
||||
<h4>Add Relays</h4>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.AddRelays} />
|
||||
</h4>
|
||||
<div className="flex mb10">
|
||||
<input
|
||||
type="text"
|
||||
@ -35,7 +40,7 @@ const RelaySettingsPage = () => {
|
||||
/>
|
||||
</div>
|
||||
<button className="secondary mb10" onClick={() => addNewRelay()}>
|
||||
Add
|
||||
<FormattedMessage {...messages.Add} />
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
@ -66,7 +71,7 @@ const RelaySettingsPage = () => {
|
||||
<div className="flex mt10">
|
||||
<div className="f-grow"></div>
|
||||
<button type="button" onClick={() => saveRelays()}>
|
||||
Save
|
||||
<FormattedMessage {...messages.Save} />
|
||||
</button>
|
||||
</div>
|
||||
{addRelay()}
|
||||
|
60
src/Pages/settings/messages.js
Normal file
60
src/Pages/settings/messages.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { defineMessages } from "react-intl";
|
||||
import { addIdAndDefaultMessageToMessages } from "Util";
|
||||
|
||||
const messages = defineMessages({
|
||||
Profile: "Profile",
|
||||
Relays: "Relays",
|
||||
Owner: "Owner",
|
||||
Software: "Software",
|
||||
Contact: "Contact",
|
||||
Supports: "Supports",
|
||||
Remove: "Remove",
|
||||
Preferences: "Preferences",
|
||||
Donate: "Donate",
|
||||
LogOut: "Log Out",
|
||||
Theme: "Theme",
|
||||
System: "System (Default)",
|
||||
Light: "Light",
|
||||
Dark: "Dark",
|
||||
AutoloadMedia: "Automatically load media",
|
||||
AutoloadMediaHelp:
|
||||
"Media in posts will automatically be shown for selected people, otherwise only the link will show",
|
||||
None: "None",
|
||||
FollowsOnly: "Follows only",
|
||||
All: "All",
|
||||
ImgProxy: "Image proxy service",
|
||||
ImgProxyHelp: "Use imgproxy to compress images",
|
||||
ServiceUrl: "Service URL",
|
||||
ServiceKey: "Service Key",
|
||||
ServiceSalt: "Service Salt",
|
||||
EnableReactions: "Enable reactions",
|
||||
EnableReactionsHelp:
|
||||
"Reactions will be shown on every page, if disabled no reactions will be shown",
|
||||
ConfirmReposts: "Confirm Reposts",
|
||||
ConfirmRepostsHelp: "Reposts need to be manually confirmed",
|
||||
ShowLatest: "Automatically show latest notes",
|
||||
ShowLatestHelp: "Notes will stream in real time into global and posts tab",
|
||||
FileUpload: "File upload service",
|
||||
FileUploadHelp: "Pick which upload service you want to upload attachments to",
|
||||
Default: "(Default)",
|
||||
DebugMenus: "Debug Menus",
|
||||
DebugMenusHelp: `Shows "Copy ID" and "Copy Event JSON" in the context menu on each message`,
|
||||
EditProfile: "Edit Profile",
|
||||
About: "About",
|
||||
LnAddress: "LN Address",
|
||||
Avatar: "Avatar",
|
||||
Banner: "Banner",
|
||||
Edit: "Edit",
|
||||
PrivateKey: "Your Private Key Is (do not share this with anyone)",
|
||||
Add: "Add",
|
||||
AddRelays: "Add Relays",
|
||||
Name: "Name",
|
||||
Profile: "Profile",
|
||||
Website: "Website",
|
||||
Save: "Save",
|
||||
DisplayName: "Display name",
|
||||
Buy: "Buy",
|
||||
Nip05: "NIP-05",
|
||||
});
|
||||
|
||||
export default addIdAndDefaultMessageToMessages(messages, "Pages.settings");
|
Reference in New Issue
Block a user