Skip to content

Commit

Permalink
feat: toast notify on publish
Browse files Browse the repository at this point in the history
  • Loading branch information
v0l committed Dec 2, 2023
1 parent 46ee738 commit cfb446c
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 144 deletions.
2 changes: 1 addition & 1 deletion packages/app/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"publicDir": "public/snort",
"httpCache": "",
"animalNamePlaceholders": false,
"showNoteBroadcaster": true,
"defaultZapPoolFee": 0.5,
"bypassImgProxyError": false,
"features": {
Expand All @@ -22,6 +21,7 @@
"signUp": {
"moderation": true
},
"noteCreatorToast": true,
"hideFromNavbar": ["/graph"],
"deckSubKind": 1,
"eventLinkPrefix": "nevent",
Expand Down
1 change: 0 additions & 1 deletion packages/app/config/iris.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"publicDir": "public/iris",
"httpCache": "https://api.iris.to",
"animalNamePlaceholders": true,
"showNoteBroadcaster": false,
"defaultZapPoolFee": 0.5,
"bypassImgProxyError": true,
"features": {
Expand Down
3 changes: 2 additions & 1 deletion packages/app/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ declare const CONFIG: {
navLogo: string | null;
httpCache: string;
animalNamePlaceholders: boolean;
showNoteBroadcaster: boolean;
defaultZapPoolFee: number;
bypassImgProxyError: boolean;
features: {
Expand All @@ -67,6 +66,8 @@ declare const CONFIG: {
hideFromNavbar: Array<string>;
// Limit deck to certain subscriber tier
deckSubKind?: number;
// Create toast notifications when publishing notes
noteCreatorToast?: boolean;
eventLinkPrefix: NostrPrefix;
profileLinkPrefix: NostrPrefix;
defaultRelays: Record<string, RelaySettings>;
Expand Down
102 changes: 0 additions & 102 deletions packages/app/src/Element/Event/Create/NoteBroadcaster.tsx

This file was deleted.

56 changes: 29 additions & 27 deletions packages/app/src/Element/Event/Create/NoteCreator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import useLogin from "@/Hooks/useLogin";
import { GetPowWorker } from "@/index";
import AsyncButton from "@/Element/Button/AsyncButton";
import { AsyncIcon } from "@/Element/Button/AsyncIcon";
import { fetchNip05Pubkey } from "@snort/shared";
import { fetchNip05Pubkey, unixNow } from "@snort/shared";
import { ZapTarget } from "@/Zapper";
import { useNoteCreator } from "@/State/NoteCreator";
import { NoteBroadcaster } from "@/Element/Event/Create/NoteBroadcaster";
import FileUploadProgress from "../FileUpload";
import { ToggleSwitch } from "@/Icons/Toggle";
import { sendEventToRelays } from "@/Element/Event/Create/util";
import { TrendingHashTagsLine } from "@/Element/Event/Create/TrendingHashTagsLine";
import { Toastore } from "@/Toaster";
import { OkResponseRow } from "./OkResponseRow";

export function NoteCreator() {
const { formatMessage } = useIntl();
Expand Down Expand Up @@ -151,15 +152,17 @@ export function NoteCreator() {
const ev = await buildNote();
if (ev) {
const events = (note.otherEvents ?? []).concat(ev);
note.update(n => {
n.sending = events;
});
if (!CONFIG.showNoteBroadcaster) {
Promise.all(events.map(a => sendEventToRelays(system, a, note.selectedCustomRelays)).flat()).catch(
console.error,
);
reset();
}
events.map(a => sendEventToRelays(system, a, note.selectedCustomRelays, r => {
if (CONFIG.noteCreatorToast) {
r.forEach(rr => {
Toastore.push({
element: <OkResponseRow rsp={rr} />,
expire: unixNow() + (rr.ok ? 5 : 55555)
})
});
}
}));
note.update(n => n.reset());
}
}

Expand Down Expand Up @@ -324,18 +327,18 @@ export function NoteCreator() {
onChange={e => {
note.update(
v =>
(v.selectedCustomRelays =
// set false if all relays selected
e.target.checked &&
(v.selectedCustomRelays =
// set false if all relays selected
e.target.checked &&
note.selectedCustomRelays &&
note.selectedCustomRelays.length == a.length - 1
? undefined
: // otherwise return selectedCustomRelays with target relay added / removed
a.filter(el =>
el === r
? e.target.checked
: !note.selectedCustomRelays || note.selectedCustomRelays.includes(el),
)),
? undefined
: // otherwise return selectedCustomRelays with target relay added / removed
a.filter(el =>
el === r
? e.target.checked
: !note.selectedCustomRelays || note.selectedCustomRelays.includes(el),
)),
);
}}
/>
Expand Down Expand Up @@ -404,9 +407,9 @@ export function NoteCreator() {
onChange={e =>
note.update(
v =>
(v.zapSplits = arr.map((vv, ii) =>
ii === i ? { ...vv, weight: Number(e.target.value) } : vv,
)),
(v.zapSplits = arr.map((vv, ii) =>
ii === i ? { ...vv, weight: Number(e.target.value) } : vv,
)),
)
}
/>
Expand Down Expand Up @@ -650,8 +653,7 @@ export function NoteCreator() {
if (!note.show) return null;
return (
<Modal id="note-creator" className="note-creator-modal" onClose={reset}>
{note.sending && <NoteBroadcaster evs={note.sending} onClose={reset} customRelays={note.selectedCustomRelays} />}
{!note.sending && noteCreatorForm()}
{noteCreatorForm()}
</Modal>
);
}
}
60 changes: 60 additions & 0 deletions packages/app/src/Element/Event/Create/OkResponseRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import AsyncButton from "@/Element/Button/AsyncButton";
import useEventPublisher from "@/Hooks/useEventPublisher";
import useLogin from "@/Hooks/useLogin";
import Icon from "@/Icons/Icon";
import { removeRelay } from "@/Login";
import { saveRelays } from "@/Pages/settings/Relays";
import { getRelayName } from "@/SnortUtils";
import { unwrap, sanitizeRelayUrl } from "@snort/shared";
import { OkResponse } from "@snort/system";
import { useState } from "react";
import { useIntl } from "react-intl";

export function OkResponseRow({ rsp }: { rsp: OkResponse }) {
const [r, setResult] = useState(rsp);
const { formatMessage } = useIntl();
const { publisher, system } = useEventPublisher();
const login = useLogin();

async function removeRelayFromResult(r: OkResponse) {
if (publisher) {
removeRelay(login, unwrap(sanitizeRelayUrl(r.relay)));
await saveRelays(system, publisher, login.relays.item);
}
}

async function retryPublish(r: OkResponse) {
const rsp = await system.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), r.event);
setResult(rsp);
}

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>}
</div>
{!r.ok && (
<div className="flex g8">
<AsyncButton
onClick={() => retryPublish(r)}
className="p4 br-compact flex items-center secondary"
title={formatMessage({
defaultMessage: "Retry publishing",
id: "9kSari",
})}>
<Icon name="refresh-ccw-01" />
</AsyncButton>
<AsyncButton
onClick={() => removeRelayFromResult(r)}
className="p4 br-compact flex items-center secondary"
title={formatMessage({
defaultMessage: "Remove from my relays",
id: "UJTWqI",
})}>
<Icon name="trash-01" className="trash-icon" />
</AsyncButton>
</div>
)}
</div>
}
1 change: 0 additions & 1 deletion packages/app/src/Feed/LoginFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export default function useLoginFeed() {
EventKind.InterestsList,
EventKind.PublicChatsList,
]);
b.withFilter().authors([pubKey]).kinds([]);
if (CONFIG.features.subscriptions && !login.readonly) {
b.withFilter().authors([pubKey]).kinds([EventKind.AppData]).tag("d", ["snort"]);
b.withFilter()
Expand Down
11 changes: 4 additions & 7 deletions packages/app/src/Toaster.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
.toaster {
position: fixed;
bottom: 0;
left: 0;
bottom: 2px;
left: 2px;
display: flex;
flex-direction: column-reverse;
z-index: 9999;
}

.toaster > .card {
border: 1px solid var(--gray);
}
gap: 4px;
}
6 changes: 3 additions & 3 deletions packages/app/src/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ToasterSlots extends ExternalStore<Array<ToastNotification>> {
#cleanup = setInterval(() => this.#eatToast(), 1000);

push(n: ToastNotification) {
n.expire ??= unixNow() + 3;
n.expire ??= unixNow() + 10;
n.id ??= uuid();
this.#stack.push(n);
this.notifyChange();
Expand Down Expand Up @@ -46,8 +46,8 @@ export default function Toaster() {
return createPortal(
<div className="toaster">
{toast.map(a => (
<div className="card flex" key={a.id}>
<Icon name={a.icon ?? "bell"} className="mr5" />
<div className="p br b flex bg-dark g8 fade-in" key={a.id}>
{a.icon && <Icon name={a.icon} />}
{a.element}
</div>
))}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ button.tall {
opacity: 1;
animation-name: fadeInOpacity;
animation-timing-function: ease-in;
animation-duration: 1s;
animation-duration: 0.5s;
}

@keyframes fadeInOpacity {
Expand Down
4 changes: 4 additions & 0 deletions packages/system/src/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface OkResponse {
id: string;
relay: string;
message?: string;
event: NostrEvent;
}

/**
Expand Down Expand Up @@ -284,6 +285,7 @@ export class Connection extends EventEmitter<ConnectionEvents> {
id: e.id,
relay: this.Address,
message: "Duplicate request",
event: e,
});
return;
}
Expand All @@ -294,6 +296,7 @@ export class Connection extends EventEmitter<ConnectionEvents> {
id: e.id,
relay: this.Address,
message: "Timeout waiting for OK response",
event: e,
});
}, timeout);

Expand All @@ -305,6 +308,7 @@ export class Connection extends EventEmitter<ConnectionEvents> {
id: id as string,
relay: this.Address,
message: message as string | undefined,
event: e,
});
});

Expand Down

0 comments on commit cfb446c

Please sign in to comment.