ErrorBoundary for notes, wip notif settings
Some checks are pending
continuous-integration/drone/push Build is running
Some checks are pending
continuous-integration/drone/push Build is running
This commit is contained in:
parent
2bf62f3a03
commit
20a0a3aea4
@ -21,7 +21,8 @@
|
|||||||
"moderation": true
|
"moderation": true
|
||||||
},
|
},
|
||||||
"defaultPreferences": {
|
"defaultPreferences": {
|
||||||
"checkSigs": true
|
"checkSigs": true,
|
||||||
|
"sentToRelayNotifications": "all"
|
||||||
},
|
},
|
||||||
"media": {
|
"media": {
|
||||||
"bypassImgProxyError": false,
|
"bypassImgProxyError": false,
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
"moderation": false
|
"moderation": false
|
||||||
},
|
},
|
||||||
"defaultPreferences": {
|
"defaultPreferences": {
|
||||||
"checkSigs": true
|
"checkSigs": true,
|
||||||
|
"sentToRelayNotifications": "none"
|
||||||
},
|
},
|
||||||
"media": {
|
"media": {
|
||||||
"bypassImgProxyError": true,
|
"bypassImgProxyError": true,
|
||||||
|
1
packages/app/custom.d.ts
vendored
1
packages/app/custom.d.ts
vendored
@ -60,6 +60,7 @@ declare const CONFIG: {
|
|||||||
};
|
};
|
||||||
defaultPreferences: {
|
defaultPreferences: {
|
||||||
checkSigs: boolean;
|
checkSigs: boolean;
|
||||||
|
sentToRelayNotifications: "none" | "all" | "failures";
|
||||||
};
|
};
|
||||||
signUp: {
|
signUp: {
|
||||||
moderation: boolean;
|
moderation: boolean;
|
||||||
|
@ -32,7 +32,6 @@ export function OkResponseRow({ rsp, close }: { rsp: OkResponse; close: () => vo
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center g16">
|
<div className="flex items-center g16">
|
||||||
<Icon name={r.ok ? "check" : "x"} className={r.ok ? "success" : "error"} size={24} />
|
|
||||||
<div className="flex flex-col grow g4">
|
<div className="flex flex-col grow g4">
|
||||||
<b>{getRelayName(r.relay)}</b>
|
<b>{getRelayName(r.relay)}</b>
|
||||||
{r.message && <small>{r.message}</small>}
|
{r.message && <small>{r.message}</small>}
|
||||||
|
@ -10,6 +10,7 @@ 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";
|
||||||
|
import ErrorBoundary from "@/Element/ErrorBoundary";
|
||||||
|
|
||||||
export interface NoteProps {
|
export interface NoteProps {
|
||||||
data: TaggedNostrEvent;
|
data: TaggedNostrEvent;
|
||||||
@ -44,29 +45,30 @@ export interface NoteProps {
|
|||||||
|
|
||||||
export default function Note(props: NoteProps) {
|
export default function Note(props: NoteProps) {
|
||||||
const { data: ev, className } = props;
|
const { data: ev, className } = props;
|
||||||
|
let content;
|
||||||
if (ev.kind === EventKind.Repost) {
|
if (ev.kind === EventKind.Repost) {
|
||||||
return <NoteReaction data={ev} key={ev.id} root={undefined} depth={(props.depth ?? 0) + 1} />;
|
content = <NoteReaction data={ev} key={ev.id} root={undefined} depth={(props.depth ?? 0) + 1} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.FileHeader) {
|
if (ev.kind === EventKind.FileHeader) {
|
||||||
return <NostrFileElement ev={ev} />;
|
content = <NostrFileElement ev={ev} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.ZapstrTrack) {
|
if (ev.kind === EventKind.ZapstrTrack) {
|
||||||
return <ZapstrEmbed ev={ev} />;
|
content = <ZapstrEmbed ev={ev} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.FollowSet || ev.kind === EventKind.ContactList) {
|
if (ev.kind === EventKind.FollowSet || ev.kind === EventKind.ContactList) {
|
||||||
return <PubkeyList ev={ev} className={className} />;
|
content = <PubkeyList ev={ev} className={className} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.LiveEvent) {
|
if (ev.kind === EventKind.LiveEvent) {
|
||||||
return <LiveEvent ev={ev} />;
|
content = <LiveEvent ev={ev} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.SetMetadata) {
|
if (ev.kind === EventKind.SetMetadata) {
|
||||||
return <ProfilePreview actions={<></>} pubkey={ev.pubkey} />;
|
content = <ProfilePreview actions={<></>} pubkey={ev.pubkey} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === (9041 as EventKind)) {
|
if (ev.kind === (9041 as EventKind)) {
|
||||||
return <ZapGoal ev={ev} />;
|
content = <ZapGoal ev={ev} />;
|
||||||
}
|
}
|
||||||
if (ev.kind === EventKind.LongFormTextNote) {
|
if (ev.kind === EventKind.LongFormTextNote) {
|
||||||
return (
|
content = (
|
||||||
<LongFormText
|
<LongFormText
|
||||||
ev={ev}
|
ev={ev}
|
||||||
related={props.related}
|
related={props.related}
|
||||||
@ -77,5 +79,6 @@ export default function Note(props: NoteProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <NoteInner {...props} />;
|
content = <NoteInner {...props} />;
|
||||||
|
return <ErrorBoundary>{content}</ErrorBoundary>;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { TimelineFragment } from "@/Element/Feed/TimelineFragment";
|
|||||||
import { DisplayAs } from "@/Element/Feed/DisplayAsSelector";
|
import { DisplayAs } from "@/Element/Feed/DisplayAsSelector";
|
||||||
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
|
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
|
||||||
import ImageGridItem from "@/Element/Feed/ImageGridItem";
|
import ImageGridItem from "@/Element/Feed/ImageGridItem";
|
||||||
|
import ErrorBoundary from "@/Element/ErrorBoundary";
|
||||||
|
|
||||||
export interface TimelineRendererProps {
|
export interface TimelineRendererProps {
|
||||||
frags: Array<TimelineFragment>;
|
frags: Array<TimelineFragment>;
|
||||||
@ -50,13 +51,15 @@ export function TimelineRenderer(props: TimelineRendererProps) {
|
|||||||
|
|
||||||
const renderNotes = () => {
|
const renderNotes = () => {
|
||||||
return props.frags.map(frag => (
|
return props.frags.map(frag => (
|
||||||
<TimelineFragment
|
<ErrorBoundary>
|
||||||
frag={frag}
|
<TimelineFragment
|
||||||
related={props.related}
|
frag={frag}
|
||||||
noteRenderer={props.noteRenderer}
|
related={props.related}
|
||||||
noteOnClick={props.noteOnClick}
|
noteRenderer={props.noteRenderer}
|
||||||
noteContext={props.noteContext}
|
noteOnClick={props.noteOnClick}
|
||||||
/>
|
noteContext={props.noteContext}
|
||||||
|
/>
|
||||||
|
</ErrorBoundary>
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import useImgProxy from "@/Hooks/useImgProxy";
|
|||||||
interface SpotlightMediaProps {
|
interface SpotlightMediaProps {
|
||||||
images: Array<string>;
|
images: Array<string>;
|
||||||
idx: number;
|
idx: number;
|
||||||
|
className: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,5 +39,5 @@ function SpotlightFromThread({ onClose }: { onClose: () => void }) {
|
|||||||
a => a.type === "media" && (a.mimeType?.startsWith("image/") || a.mimeType?.startsWith("video/")),
|
a => a.type === "media" && (a.mimeType?.startsWith("image/") || a.mimeType?.startsWith("video/")),
|
||||||
);
|
);
|
||||||
if (images.length === 0) return;
|
if (images.length === 0) return;
|
||||||
return <SpotlightMedia images={images.map(a => a.content)} idx={0} onClose={onClose} />;
|
return <SpotlightMedia className="w-full" images={images.map(a => a.content)} idx={0} onClose={onClose} />;
|
||||||
}
|
}
|
||||||
|
39
packages/app/src/Pages/settings/Notifications.tsx
Normal file
39
packages/app/src/Pages/settings/Notifications.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import "./Preferences.css";
|
||||||
|
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
import useLogin from "@/Hooks/useLogin";
|
||||||
|
import { updatePreferences } from "@/Login";
|
||||||
|
import { useLocale } from "@/IntlProvider";
|
||||||
|
|
||||||
|
const PreferencesPage = () => {
|
||||||
|
const { id, perf } = useLogin(s => ({ id: s.id, perf: s.appData.item.preferences }));
|
||||||
|
const { lang } = useLocale();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="preferences flex flex-col g24">
|
||||||
|
<h3>
|
||||||
|
<FormattedMessage defaultMessage="Notifications" id="NAidKb" />
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div className="flex justify-between w-max">
|
||||||
|
<h4>
|
||||||
|
<FormattedMessage defaultMessage="Language" id="y1Z3or" />
|
||||||
|
</h4>
|
||||||
|
<div>
|
||||||
|
<select
|
||||||
|
value={lang}
|
||||||
|
onChange={e =>
|
||||||
|
updatePreferences(id, {
|
||||||
|
...perf,
|
||||||
|
language: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
style={{ textTransform: "capitalize" }}>
|
||||||
|
<option value={1}>asdf</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default PreferencesPage;
|
@ -39,6 +39,11 @@ const SettingsIndex = () => {
|
|||||||
{ icon: "shield-tick", message: <FormattedMessage defaultMessage="Moderation" id="wofVHy" />, path: "moderation" },
|
{ icon: "shield-tick", message: <FormattedMessage defaultMessage="Moderation" id="wofVHy" />, path: "moderation" },
|
||||||
{ icon: "badge", message: <FormattedMessage defaultMessage="Nostr Address" id="9pMqYs" />, path: "handle" },
|
{ icon: "badge", message: <FormattedMessage defaultMessage="Nostr Address" id="9pMqYs" />, path: "handle" },
|
||||||
{ icon: "gear", message: <FormattedMessage defaultMessage="Preferences" id="PCSt5T" />, path: "preferences" },
|
{ icon: "gear", message: <FormattedMessage defaultMessage="Preferences" id="PCSt5T" />, path: "preferences" },
|
||||||
|
{
|
||||||
|
icon: "bell-outline",
|
||||||
|
message: <FormattedMessage defaultMessage="Notifications" id="NAidKb" />,
|
||||||
|
path: "notifications",
|
||||||
|
},
|
||||||
{ icon: "wallet", message: <FormattedMessage defaultMessage="Wallet" id="3yk8fB" />, path: "wallet" },
|
{ icon: "wallet", message: <FormattedMessage defaultMessage="Wallet" id="3yk8fB" />, path: "wallet" },
|
||||||
{ icon: "heart", message: <FormattedMessage defaultMessage="Donate" id="2IFGap" />, path: "/donate" },
|
{ icon: "heart", message: <FormattedMessage defaultMessage="Donate" id="2IFGap" />, path: "/donate" },
|
||||||
{ icon: "hard-drive", message: <FormattedMessage defaultMessage="Cache" id="DBiVK1" />, path: "cache" },
|
{ icon: "hard-drive", message: <FormattedMessage defaultMessage="Cache" id="DBiVK1" />, path: "cache" },
|
||||||
|
@ -3,15 +3,16 @@ import SettingsIndex from "@/Pages/settings/Root";
|
|||||||
import Profile from "@/Pages/settings/Profile";
|
import Profile from "@/Pages/settings/Profile";
|
||||||
import Relay from "@/Pages/settings/Relays";
|
import Relay from "@/Pages/settings/Relays";
|
||||||
import Preferences from "@/Pages/settings/Preferences";
|
import Preferences from "@/Pages/settings/Preferences";
|
||||||
|
//import Notifications from "@/Pages/settings/Notifications";
|
||||||
import RelayInfo from "@/Pages/settings/RelayInfo";
|
import RelayInfo from "@/Pages/settings/RelayInfo";
|
||||||
import AccountsPage from "@/Pages/settings/Accounts";
|
import AccountsPage from "@/Pages/settings/Accounts";
|
||||||
import { WalletSettingsRoutes } from "@/Pages/settings/WalletSettings";
|
import { WalletSettingsRoutes } from "@/Pages/settings/WalletSettings";
|
||||||
import { ManageHandleRoutes } from "@/Pages/settings/handle";
|
import { ManageHandleRoutes } from "@/Pages/settings/handle";
|
||||||
import ExportKeys from "@/Pages/settings/Keys";
|
import ExportKeys from "@/Pages/settings/Keys";
|
||||||
import ModerationSettings from "@/Pages/settings/Moderation";
|
import ModerationSettings from "@/Pages/settings/Moderation";
|
||||||
import { CacheSettings } from "./settings/Cache";
|
import { CacheSettings } from "./Cache";
|
||||||
|
|
||||||
import { ReferralsPage } from "./settings/Referrals";
|
import { ReferralsPage } from "./Referrals";
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
return (
|
return (
|
||||||
@ -42,6 +43,12 @@ export const SettingsRoutes: RouteObject[] = [
|
|||||||
path: "preferences",
|
path: "preferences",
|
||||||
element: <Preferences />,
|
element: <Preferences />,
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
path: "notifications",
|
||||||
|
element: <Notifications />,
|
||||||
|
},
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
path: "accounts",
|
path: "accounts",
|
||||||
element: <AccountsPage />,
|
element: <AccountsPage />,
|
@ -40,7 +40,7 @@ import Layout from "@/Pages/Layout";
|
|||||||
import ProfilePage from "@/Pages/Profile/ProfilePage";
|
import ProfilePage from "@/Pages/Profile/ProfilePage";
|
||||||
import { RootRoutes, RootTabRoutes } from "@/Pages/Root";
|
import { RootRoutes, RootTabRoutes } from "@/Pages/Root";
|
||||||
import NotificationsPage from "@/Pages/Notifications/Notifications";
|
import NotificationsPage from "@/Pages/Notifications/Notifications";
|
||||||
import SettingsPage, { SettingsRoutes } from "@/Pages/SettingsPage";
|
import SettingsPage, { SettingsRoutes } from "@/Pages/settings/SettingsPage";
|
||||||
import ErrorPage from "@/Pages/ErrorPage";
|
import ErrorPage from "@/Pages/ErrorPage";
|
||||||
import NostrAddressPage from "@/Pages/NostrAddressPage";
|
import NostrAddressPage from "@/Pages/NostrAddressPage";
|
||||||
import MessagesPage from "@/Pages/Messages/MessagesPage";
|
import MessagesPage from "@/Pages/Messages/MessagesPage";
|
||||||
|
Loading…
Reference in New Issue
Block a user