ErrorBoundary for notes, wip notif settings

This commit is contained in:
Martti Malmi 2023-12-14 15:29:27 +02:00
parent 2bf62f3a03
commit 20a0a3aea4
12 changed files with 83 additions and 23 deletions

View File

@ -21,7 +21,8 @@
"moderation": true
},
"defaultPreferences": {
"checkSigs": true
"checkSigs": true,
"sentToRelayNotifications": "all"
},
"media": {
"bypassImgProxyError": false,

View File

@ -21,7 +21,8 @@
"moderation": false
},
"defaultPreferences": {
"checkSigs": true
"checkSigs": true,
"sentToRelayNotifications": "none"
},
"media": {
"bypassImgProxyError": true,

View File

@ -60,6 +60,7 @@ declare const CONFIG: {
};
defaultPreferences: {
checkSigs: boolean;
sentToRelayNotifications: "none" | "all" | "failures";
};
signUp: {
moderation: boolean;

View File

@ -32,7 +32,6 @@ export function OkResponseRow({ rsp, close }: { rsp: OkResponse; close: () => vo
return (
<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">
<b>{getRelayName(r.relay)}</b>
{r.message && <small>{r.message}</small>}

View File

@ -10,6 +10,7 @@ import NoteReaction from "@/Element/Event/NoteReaction";
import ProfilePreview from "@/Element/User/ProfilePreview";
import { NoteInner } from "./NoteInner";
import { LongFormText } from "./LongFormText";
import ErrorBoundary from "@/Element/ErrorBoundary";
export interface NoteProps {
data: TaggedNostrEvent;
@ -44,29 +45,30 @@ export interface NoteProps {
export default function Note(props: NoteProps) {
const { data: ev, className } = props;
let content;
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) {
return <NostrFileElement ev={ev} />;
content = <NostrFileElement ev={ev} />;
}
if (ev.kind === EventKind.ZapstrTrack) {
return <ZapstrEmbed ev={ev} />;
content = <ZapstrEmbed ev={ev} />;
}
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) {
return <LiveEvent ev={ev} />;
content = <LiveEvent ev={ev} />;
}
if (ev.kind === EventKind.SetMetadata) {
return <ProfilePreview actions={<></>} pubkey={ev.pubkey} />;
content = <ProfilePreview actions={<></>} pubkey={ev.pubkey} />;
}
if (ev.kind === (9041 as EventKind)) {
return <ZapGoal ev={ev} />;
content = <ZapGoal ev={ev} />;
}
if (ev.kind === EventKind.LongFormTextNote) {
return (
content = (
<LongFormText
ev={ev}
related={props.related}
@ -77,5 +79,6 @@ export default function Note(props: NoteProps) {
);
}
return <NoteInner {...props} />;
content = <NoteInner {...props} />;
return <ErrorBoundary>{content}</ErrorBoundary>;
}

View File

@ -8,6 +8,7 @@ import { TimelineFragment } from "@/Element/Feed/TimelineFragment";
import { DisplayAs } from "@/Element/Feed/DisplayAsSelector";
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
import ImageGridItem from "@/Element/Feed/ImageGridItem";
import ErrorBoundary from "@/Element/ErrorBoundary";
export interface TimelineRendererProps {
frags: Array<TimelineFragment>;
@ -50,13 +51,15 @@ export function TimelineRenderer(props: TimelineRendererProps) {
const renderNotes = () => {
return props.frags.map(frag => (
<TimelineFragment
frag={frag}
related={props.related}
noteRenderer={props.noteRenderer}
noteOnClick={props.noteOnClick}
noteContext={props.noteContext}
/>
<ErrorBoundary>
<TimelineFragment
frag={frag}
related={props.related}
noteRenderer={props.noteRenderer}
noteOnClick={props.noteOnClick}
noteContext={props.noteContext}
/>
</ErrorBoundary>
));
};

View File

@ -7,6 +7,7 @@ import useImgProxy from "@/Hooks/useImgProxy";
interface SpotlightMediaProps {
images: Array<string>;
idx: number;
className: string;
onClose: () => void;
}

View File

@ -39,5 +39,5 @@ function SpotlightFromThread({ onClose }: { onClose: () => void }) {
a => a.type === "media" && (a.mimeType?.startsWith("image/") || a.mimeType?.startsWith("video/")),
);
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} />;
}

View 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;

View File

@ -39,6 +39,11 @@ const SettingsIndex = () => {
{ icon: "shield-tick", message: <FormattedMessage defaultMessage="Moderation" id="wofVHy" />, path: "moderation" },
{ icon: "badge", message: <FormattedMessage defaultMessage="Nostr Address" id="9pMqYs" />, path: "handle" },
{ icon: "gear", message: <FormattedMessage defaultMessage="Preferences" id="PCSt5T" />, path: "preferences" },
{
icon: "bell-outline",
message: <FormattedMessage defaultMessage="Notifications" id="NAidKb" />,
path: "notifications",
},
{ icon: "wallet", message: <FormattedMessage defaultMessage="Wallet" id="3yk8fB" />, path: "wallet" },
{ icon: "heart", message: <FormattedMessage defaultMessage="Donate" id="2IFGap" />, path: "/donate" },
{ icon: "hard-drive", message: <FormattedMessage defaultMessage="Cache" id="DBiVK1" />, path: "cache" },

View File

@ -3,15 +3,16 @@ import SettingsIndex from "@/Pages/settings/Root";
import Profile from "@/Pages/settings/Profile";
import Relay from "@/Pages/settings/Relays";
import Preferences from "@/Pages/settings/Preferences";
//import Notifications from "@/Pages/settings/Notifications";
import RelayInfo from "@/Pages/settings/RelayInfo";
import AccountsPage from "@/Pages/settings/Accounts";
import { WalletSettingsRoutes } from "@/Pages/settings/WalletSettings";
import { ManageHandleRoutes } from "@/Pages/settings/handle";
import ExportKeys from "@/Pages/settings/Keys";
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() {
return (
@ -42,6 +43,12 @@ export const SettingsRoutes: RouteObject[] = [
path: "preferences",
element: <Preferences />,
},
/*
{
path: "notifications",
element: <Notifications />,
},
*/
{
path: "accounts",
element: <AccountsPage />,

View File

@ -40,7 +40,7 @@ import Layout from "@/Pages/Layout";
import ProfilePage from "@/Pages/Profile/ProfilePage";
import { RootRoutes, RootTabRoutes } from "@/Pages/Root";
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 NostrAddressPage from "@/Pages/NostrAddressPage";
import MessagesPage from "@/Pages/Messages/MessagesPage";