This commit is contained in:
Kieran 2024-03-04 12:23:23 +00:00
commit 6785ef72e1
35 changed files with 157 additions and 213 deletions

View File

@ -149,7 +149,9 @@ export function LongFormText(props: LongFormTextProps) {
}
return (
<div className={classNames("long-form-note flex flex-col g16 p break-words")}>
<div
className={classNames("long-form-note flex flex-col g16 p break-words", { "cursor-pointer": props.isPreview })}
onClick={props.onClick}>
<ProfilePreview
pubkey={props.ev.pubkey}
actions={

View File

@ -2,7 +2,7 @@ import "./Thread.css";
import { EventExt, TaggedNostrEvent, u256 } from "@snort/system";
import { ReactNode, useCallback, useContext, useMemo } from "react";
import { useIntl } from "react-intl";
import { FormattedMessage, useIntl } from "react-intl";
import { useNavigate } from "react-router-dom";
import BackButton from "@/Components/Button/BackButton";
@ -72,6 +72,22 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
}
}
function renderCurrent() {
if (thread.current) {
const note = thread.data.find(n => n.id === thread.current);
return (
note && (
<Note
data={note}
options={{ showReactionsLink: true, showMediaSpotlight: true }}
threadChains={thread.chains}
onClick={navigateThread}
/>
)
);
}
}
function goBack() {
if (parent) {
thread.setCurrent(parent);
@ -119,6 +135,12 @@ export function Thread(props: { onBack?: () => void; disableSpotlight?: boolean
<div className="main-content">
{thread.root && renderRoot(thread.root)}
{thread.root && renderChain(chainKey(thread.root))}
{!thread.root && renderCurrent()}
{!thread.root && !thread.current && (
<NoteGhost>
<FormattedMessage defaultMessage="Looking up thread..." id="JA+tz3" />
</NoteGhost>
)}
</div>
</>
);

View File

@ -1,9 +1,9 @@
import { useContext } from "react";
import { useArticles } from "@/Feed/ArticlesFeed";
import { DeckContext } from "@/Pages/DeckLayout";
import { DeckContext } from "@/Pages/Deck/DeckLayout";
import Note from "../Event/EventComponent";
import Note from "../../Components/Event/EventComponent";
const options = {
longFormPreview: true,

View File

@ -0,0 +1,88 @@
import { NostrLink } from "@snort/system";
import { useCallback } from "react";
import { FormattedMessage } from "react-intl";
import { Outlet } from "react-router-dom";
import { RootTabs } from "@/Components/Feed/RootTabs";
import TimelineFollows from "@/Components/Feed/TimelineFollows";
import Icon from "@/Components/Icons/Icon";
import { transformTextCached } from "@/Hooks/useTextTransformCache";
import Articles from "@/Pages/Deck/Articles";
import NotificationsPage from "@/Pages/Notifications/Notifications";
export function NotesCol() {
return (
<div>
<div className="deck-col-header flex">
<div className="flex flex-1 g8">
<Icon name="rows-01" size={24} />
<FormattedMessage defaultMessage="Notes" id="7+Domh" />
</div>
<div className="flex-1">
<RootTabs base="/deck" />
</div>
</div>
<div>
<Outlet />
</div>
</div>
);
}
export function ArticlesCol() {
return (
<div>
<div className="deck-col-header flex g8">
<Icon name="file-06" size={24} />
<FormattedMessage defaultMessage="Articles" id="3KNMbJ" />
</div>
<div>
<Articles />
</div>
</div>
);
}
export function MediaCol({ setThread }: { setThread: (e: NostrLink) => void }) {
const noteOnClick = useCallback(
e => {
setThread(NostrLink.fromEvent(e));
},
[setThread],
);
return (
<div>
<div className="flex items-center gap-2 p-2 border-b border-border-color">
<Icon name="camera-lens" size={24} />
<FormattedMessage defaultMessage="Media" id="hmZ3Bz" />
</div>
<TimelineFollows
postsOnly={true}
liveStreams={false}
noteFilter={e => {
const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return images.length > 0;
}}
displayAs="grid"
showDisplayAsSelector={false}
noteOnClick={noteOnClick}
/>
</div>
);
}
export function NotificationsCol({ setThread }: { setThread: (e: NostrLink) => void }) {
return (
<div>
<div className="deck-col-header flex g8">
<Icon name="bell-solid" size={24} />
<FormattedMessage defaultMessage="Notifications" id="NAidKb" />
</div>
<div>
<NotificationsPage onClick={setThread} />
</div>
</div>
);
}

View File

@ -1,31 +1,25 @@
import "./Deck.css";
import { NostrLink, TaggedNostrEvent } from "@snort/system";
import { createContext, useCallback, useEffect, useState } from "react";
import { createContext, useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
import ErrorBoundary from "@/Components/ErrorBoundary";
import { LongFormText } from "@/Components/Event/LongFormText";
import Articles from "@/Components/Feed/Articles";
import { RootTabs } from "@/Components/Feed/RootTabs";
import TimelineFollows from "@/Components/Feed/TimelineFollows";
import Icon from "@/Components/Icons/Icon";
import Modal from "@/Components/Modal/Modal";
import { SpotlightThreadModal } from "@/Components/Spotlight/SpotlightThreadModal";
import Toaster from "@/Components/Toaster/Toaster";
import useLoginFeed from "@/Feed/LoginFeed";
import useLogin from "@/Hooks/useLogin";
import { useLoginRelays } from "@/Hooks/useLoginRelays";
import { transformTextCached } from "@/Hooks/useTextTransformCache";
import { useTheme } from "@/Hooks/useTheme";
import { ArticlesCol, MediaCol, NotesCol, NotificationsCol } from "@/Pages/Deck/Columns";
import NavSidebar from "@/Pages/Layout/NavSidebar";
import { mapPlanName } from "@/Pages/subscribe/utils";
import { trackEvent } from "@/Utils";
import { getCurrentSubscription } from "@/Utils/Subscription";
import NotificationsPage from "./Notifications/Notifications";
type Cols = "notes" | "articles" | "media" | "streams" | "notifications";
interface DeckState {
@ -153,80 +147,3 @@ export function SnortDeckLayout() {
</div>
);
}
function NotesCol() {
return (
<div>
<div className="deck-col-header flex">
<div className="flex flex-1 g8">
<Icon name="rows-01" size={24} />
<FormattedMessage defaultMessage="Notes" id="7+Domh" />
</div>
<div className="flex-1">
<RootTabs base="/deck" />
</div>
</div>
<div>
<Outlet />
</div>
</div>
);
}
function ArticlesCol() {
return (
<div>
<div className="deck-col-header flex g8">
<Icon name="file-06" size={24} />
<FormattedMessage defaultMessage="Articles" id="3KNMbJ" />
</div>
<div>
<Articles />
</div>
</div>
);
}
function MediaCol({ setThread }: { setThread: (e: NostrLink) => void }) {
const noteOnClick = useCallback(
e => {
setThread(NostrLink.fromEvent(e));
},
[setThread],
);
return (
<div>
<div className="flex items-center gap-2 p-2 border-b border-border-color">
<Icon name="camera-lens" size={24} />
<FormattedMessage defaultMessage="Media" id="hmZ3Bz" />
</div>
<TimelineFollows
postsOnly={true}
liveStreams={false}
noteFilter={e => {
const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return images.length > 0;
}}
displayAs="grid"
showDisplayAsSelector={false}
noteOnClick={noteOnClick}
/>
</div>
);
}
function NotificationsCol({ setThread }: { setThread: (e: NostrLink) => void }) {
return (
<div>
<div className="deck-col-header flex g8">
<Icon name="bell-solid" size={24} />
<FormattedMessage defaultMessage="Notifications" id="NAidKb" />
</div>
<div>
<NotificationsPage onClick={setThread} />
</div>
</div>
);
}

View File

@ -6,7 +6,7 @@ import { Link } from "react-router-dom";
import TimelineFollows from "@/Components/Feed/TimelineFollows";
import { TaskList } from "@/Components/Tasks/TaskList";
import useLogin from "@/Hooks/useLogin";
import { DeckContext } from "@/Pages/DeckLayout";
import { DeckContext } from "@/Pages/Deck/DeckLayout";
import messages from "@/Pages/messages";
const FollowsHint = () => {

View File

@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { useIntl } from "react-intl";
import { useNavigate, useParams } from "react-router-dom";
import Timeline from "@/Components/Feed/Timeline";
@ -25,7 +25,6 @@ const SearchPage = () => {
const { formatMessage } = useIntl();
const [search, setSearch] = useState<string>(params.keyword ?? "");
const [keyword, setKeyword] = useState<string>(params.keyword ?? "");
const [sortPopular, setSortPopular] = useState<boolean>(true);
// tabs
const SearchTab = [
{ text: formatMessage({ defaultMessage: "Notes", id: "7+Domh" }), value: NOTES },
@ -56,10 +55,10 @@ const SearchPage = () => {
const subject = useMemo(
() => ({
type: "post_keyword",
items: [keyword + (sortPopular ? " sort:popular" : "")],
items: [keyword],
discriminator: keyword,
}),
[keyword, sortPopular],
[keyword],
);
function tabContent() {
@ -71,29 +70,7 @@ const SearchPage = () => {
return <TrendingNotes />;
}
return (
<>
{sortOptions()}
<Timeline key={keyword} subject={subject} postsOnly={false} method={"LIMIT_UNTIL"} loadMore={false} />
</>
);
}
function sortOptions() {
if (tab.value != PROFILES) return null;
return (
<div className="flex items-center justify-end g8">
<FormattedMessage defaultMessage="Sort" id="RwFaYs" description="Label for sorting options for people search" />
<select onChange={e => setSortPopular(e.target.value == "true")} value={sortPopular ? "true" : "false"}>
<option value={"true"}>
<FormattedMessage defaultMessage="Popular" id="mTJFgF" description="Sort order name" />
</option>
<option value={"false"}>
<FormattedMessage defaultMessage="Recent" id="RjpoYG" description="Sort order name" />
</option>
</select>
</div>
);
return <Timeline key={keyword} subject={subject} postsOnly={false} method={"LIMIT_UNTIL"} loadMore={false} />;
}
return (

View File

@ -14,7 +14,7 @@ import { db } from "@/Db";
import { addCachedMetadataToFuzzySearch } from "@/Db/FuzzySearch";
import { updateRelayConnections } from "@/Hooks/useLoginRelays";
import { AboutPage } from "@/Pages/About";
import { SnortDeckLayout } from "@/Pages/DeckLayout";
import { SnortDeckLayout } from "@/Pages/Deck/DeckLayout";
import DonatePage from "@/Pages/Donate/DonatePage";
import ErrorPage from "@/Pages/ErrorPage";
import FreeNostrAddressPage from "@/Pages/FreeNostrAddressPage";

View File

@ -631,6 +631,9 @@
"J2HeQ+": {
"defaultMessage": "Use commas to separate words e.g. word1, word2, word3"
},
"JA+tz3": {
"defaultMessage": "Looking up thread..."
},
"JCIgkj": {
"defaultMessage": "Username"
},
@ -856,20 +859,12 @@
"RhDAoS": {
"defaultMessage": "Are you sure you want to delete {id}"
},
"RjpoYG": {
"defaultMessage": "Recent",
"description": "Sort order name"
},
"RoOyAh": {
"defaultMessage": "Relays"
},
"Rs4kCE": {
"defaultMessage": "Bookmark"
},
"RwFaYs": {
"defaultMessage": "Sort",
"description": "Label for sorting options for people search"
},
"SLZGPn": {
"defaultMessage": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}."
},
@ -1458,10 +1453,6 @@
"mKhgP9": {
"defaultMessage": "{n,plural,=0{} =1{zapped} other{zapped}}"
},
"mTJFgF": {
"defaultMessage": "Popular",
"description": "Sort order name"
},
"mfe8RW": {
"defaultMessage": "Option: {n}"
},

View File

@ -208,6 +208,7 @@
"J+dIsA": "الإشتراكات",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "استخدام فواصل لفصل الكلمات على سبيل المثال الكلمات 1 و 2 و 3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "اسم المستخدم",
"JGrt9q": "إرسال الجلوس إلى {name}",
"JHEHCk": "وميض ({n})",
@ -282,10 +283,8 @@
"RahCRH": "منتهي الصلاحية",
"RfhLwC": "لـ: {author}",
"RhDAoS": "هل أنت متأكد أنك تريد حذف {id}",
"RjpoYG": "حديثاً",
"RoOyAh": "موصّلات",
"Rs4kCE": "المنشورات المرجعية",
"RwFaYs": "فرز",
"SLZGPn": "أدخل دبوس لتشفير المفتاح الخاص، يجب عليك إدخال هذا الدبوس في كل مرة تفتح فيها {site}.",
"SMO+on": "إرسال زاب إلى {name}",
"SOqbe9": "تحديث عنوان البرق",
@ -481,7 +480,6 @@
"mKAr6h": "تابع الكل",
"mKh2HS": "خدمة تحميل الملفات",
"mKhgP9": "{n,plural,=0{}=1{ومّض}other{ومّض}}",
"mTJFgF": "شعبية",
"mfe8RW": "خيار: {n}",
"n1Whvj": "تبديل",
"nDejmx": "رفع الحظر",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Abonnements",
"J1iLmb": "Benachrichtigungen nicht erlaubt",
"J2HeQ+": "Benutze Kommas um Wörter zu trennen, z.B. Wort1, Wort2, Wort3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Benutzername",
"JGrt9q": "Sats an {name} senden",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Abgelaufen",
"RfhLwC": "Von: {author}",
"RhDAoS": "Sind sie sicher, dass sie {id} löschen möchten?",
"RjpoYG": "Neueste",
"RoOyAh": "Relais",
"Rs4kCE": "Lesezeichen",
"RwFaYs": "Sortieren",
"SLZGPn": "Gib eine PIN ein, um deinen privaten Schlüssel zu verschlüsseln. Du musst diese PIN jedes Mal eingeben, wenn du {site} öffnest.",
"SMO+on": "Zap an {name} senden",
"SOqbe9": "Lightning-Adresse aktualisieren",
@ -345,7 +344,7 @@
"YDURw6": "URL des Dienstes",
"YR2I9M": "Keine Schlüssel, kein {app}. Es gibt keine Möglichkeit, sie zurückzusetzen, wenn du keine Sicherungskopie gemacht hast. Es dauert nur eine Minute.",
"YXA3AH": "Reaktionen aktivieren",
"Yf3DwC": "Verbinde eine Wallet um sofortigeZahlungen zu senden",
"Yf3DwC": "Verbinde eine Wallet, um sofortige Zahlungen zu senden",
"Z4BMCZ": "Verbindungs-Passphrase eingeben",
"ZKORll": "Jetzt aktivieren",
"ZLmyG9": "Mitwirkende",
@ -481,7 +480,6 @@
"mKAr6h": "Allen folgen",
"mKh2HS": "Datei-Upload-Dienst",
"mKhgP9": "{n,plural,=0{} =1{hat gezappt} other{haben gezappt}}",
"mTJFgF": "Beliebt",
"mfe8RW": "Option: {n}",
"n1Whvj": "Wechseln",
"nDejmx": "Freigeben",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Subscriptions",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Use commas to separate words e.g. word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Username",
"JGrt9q": "Send sats to {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Expired",
"RfhLwC": "By: {author}",
"RhDAoS": "Are you sure you want to delete {id}",
"RjpoYG": "Recent",
"RoOyAh": "Relays",
"Rs4kCE": "Bookmark",
"RwFaYs": "Sort",
"SLZGPn": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.",
"SMO+on": "Send zap to {name}",
"SOqbe9": "Update Lightning Address",
@ -481,7 +480,6 @@
"mKAr6h": "Follow all",
"mKh2HS": "File upload service",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Popular",
"mfe8RW": "Option: {n}",
"n1Whvj": "Switch",
"nDejmx": "Unblock",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Suscripciones",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Utiliza comas para separar palabras, por ejemplo: palabra1, palabra2, palabra3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Usuario",
"JGrt9q": "Enviar saturación a {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Caducada",
"RfhLwC": "Por: {author}",
"RhDAoS": "¿Estás seguro de que quieres eliminar {id}?",
"RjpoYG": "Recientes",
"RoOyAh": "Relays",
"Rs4kCE": "Favorito",
"RwFaYs": "Ordenar",
"SLZGPn": "Introduce un pin para encriptar tu clave privada, debes introducir este pin cada vez que abras {site}.",
"SMO+on": "Enviar zap a {name}",
"SOqbe9": "Actualizar la dirección de relámpago",
@ -481,7 +480,6 @@
"mKAr6h": "Seguir todos",
"mKh2HS": "Subida de ficheros",
"mKhgP9": "{n, plural, =0 {} =1 {zapeó} other {zapearon}}",
"mTJFgF": "Populares",
"mfe8RW": "Opción: {n}",
"n1Whvj": "Cambia",
"nDejmx": "Desbloquear",

View File

@ -208,6 +208,7 @@
"J+dIsA": "اشتراک",
"J1iLmb": "اعلان ها مجاز نیستند",
"J2HeQ+": "از ویرگول برای جدا کردن کلمات استفاده کنید. مثال کلمه ۱، کلمه ۲، کلمه۳",
"JA+tz3": "Looking up thread...",
"JCIgkj": "نام کاربری",
"JGrt9q": "ارسال ساتوشی به {name}",
"JHEHCk": "زپ ({n})",
@ -282,10 +283,8 @@
"RahCRH": "منقضی شده",
"RfhLwC": "توسط: {author}",
"RhDAoS": "مطمئنید می خواهید {id} را حذف کنید",
"RjpoYG": "اخیر",
"RoOyAh": "رله",
"Rs4kCE": "نشانک",
"RwFaYs": "چینش",
"SLZGPn": "یک پین وارد کنید تا کلید خصوصی تان را رمزگذاری کنید، باید این پین را هر بار هنگام ورود به {site} وارد کنید.",
"SMO+on": "زپ زدن به {name}",
"SOqbe9": "بروزرسانی آدرس لایتنینگ",
@ -481,7 +480,6 @@
"mKAr6h": "دنبال کردن همه",
"mKh2HS": "خدمات بارگذاری فایل",
"mKhgP9": "{n,plural,one {}=0{} =1{زپ شده} other{زپ شده}}",
"mTJFgF": "محبوب",
"mfe8RW": "گزینه: {n}",
"n1Whvj": "تعویض",
"nDejmx": "لغو مسدودی",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Tilaukset",
"J1iLmb": "Ilmoituksia ei sallita",
"J2HeQ+": "Käytä pilkkuja erottamaan sanat toisistaan, esim. sana1, sana2, sana3.",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Käyttäjätunnus",
"JGrt9q": "Lähetä satseja käyttäjälle {name}",
"JHEHCk": "Zapit ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Vanhentunut",
"RfhLwC": "Tekijä: {author}",
"RhDAoS": "Haluatko varmasti poistaa {id}",
"RjpoYG": "Viimeaikaiset",
"RoOyAh": "Välittäjät",
"Rs4kCE": "Kirjanmerkki",
"RwFaYs": "Lajittelu",
"SLZGPn": "Syötä pin yksityisen avaimesi salaamista varten, sinun on syötettävä tämä pin joka kerta, kun avaat {site}.",
"SMO+on": "Lähetä satseja käyttäjälle {name}",
"SOqbe9": "Päivitä Lightning-osoite",
@ -481,7 +480,6 @@
"mKAr6h": "Seuraa kaikkia",
"mKh2HS": "Tiedostojen latauspalvelu",
"mKhgP9": "{n,plural,=0{} =1{zappasi} other{zappasivat}}",
"mTJFgF": "Suosittu",
"mfe8RW": "Vaihtoehto: {n}",
"n1Whvj": "Vaihda",
"nDejmx": "Poista esto",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Abonnements",
"J1iLmb": "Notifications non autorisées",
"J2HeQ+": "Utiliser des virgules pour séparer les mots, par exemple mot1, mot2, mot3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Nom dutilisateur",
"JGrt9q": "Envoyer des sats à {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Expiré",
"RfhLwC": "Par : {author}",
"RhDAoS": "Êtes-vous sûr que vous voulez supprimer {id}",
"RjpoYG": "Récent",
"RoOyAh": "Relais",
"Rs4kCE": "Favori",
"RwFaYs": "Trier",
"SLZGPn": "Saisissez un code PIN pour crypter votre clé privée. Vous devez saisir ce code PIN à chaque fois que vous ouvrez le site {site}.",
"SMO+on": "Envoyer zap à {name}",
"SOqbe9": "Mettre à jour l'adresse Lightning",
@ -481,7 +480,6 @@
"mKAr6h": "Suivre tout",
"mKh2HS": "Service d'hébergement de fichiers",
"mKhgP9": "{n,plural,=0{} =1{zappé} other{zappé}}",
"mTJFgF": "Populaire",
"mfe8RW": "Option : {n}",
"n1Whvj": "Changer",
"nDejmx": "Débloquer",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Pretplate",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Use commas to separate words e.g. word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Korisničko ime",
"JGrt9q": "Send sats to {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Isteklo",
"RfhLwC": "Od: {author}",
"RhDAoS": "Jeste li sigurni da želite obrisati {id}",
"RjpoYG": "Recent",
"RoOyAh": "Releji",
"Rs4kCE": "Oznaka",
"RwFaYs": "Sort",
"SLZGPn": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.",
"SMO+on": "Send zap to {name}",
"SOqbe9": "Ažuriraj Lightning Adresu",
@ -481,7 +480,6 @@
"mKAr6h": "Prati sve",
"mKh2HS": "Usluga učitavanja datoteka",
"mKhgP9": "{n,plural,=0{} =1{zappan} other{zappano}}",
"mTJFgF": "Popular",
"mfe8RW": "Mogućnosti: {n}",
"n1Whvj": "Promijeni",
"nDejmx": "Odblokiraj",

View File

@ -43,7 +43,7 @@
"2/2yg+": "Hozzáad",
"25V4l1": "Banner",
"25WwxF": "Nincs fiókja?",
"2IFGap": "Adományoz",
"2IFGap": "Adományozás",
"2LbrkB": "Add meg jelszavad",
"2O2sfp": "Befejezés",
"2a2YiP": "{n} könyvjelző",
@ -208,6 +208,7 @@
"J+dIsA": "Előfizetések",
"J1iLmb": "Az értesítések nincsenek engedélyezve",
"J2HeQ+": "Szavak elválasztása vesszőkkel, pl. word1, word2, word3.",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Felhasználónév",
"JGrt9q": "Sat-ok küldése {name}",
"JHEHCk": "Zap-ek ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Lejárt",
"RfhLwC": "Írta: {author}",
"RhDAoS": "Biztos hogy törölni akarod a {id}",
"RjpoYG": "Legutóbbi",
"RoOyAh": "Csomópontok",
"Rs4kCE": "Könyvjelző",
"RwFaYs": "Rendezés",
"SLZGPn": "A privát kulcs titkosításához adjon meg egy PIN-kódot. Ezt a PIN-kódot minden alkalommal meg kell adnod, amikor a(z) {site}-ot megnyitod.",
"SMO+on": "Sat küldése {name}",
"SOqbe9": "Lightning cím frissítése",
@ -417,7 +416,7 @@
"fqwcJ1": "On-chain Adomány",
"fsB/4p": "Mentve",
"furjvW": "Stream megtekintése",
"g5pX+a": "Rólam",
"g5pX+a": "Rólunk",
"g985Wp": "A szavazás elküldése sikertelen",
"gDzDRs": "Emoji küldése, amikor egy bejegyzésre reagál",
"gXgY3+": "Nem minden kliens támogatja",
@ -481,7 +480,6 @@
"mKAr6h": "Követem mindet",
"mKh2HS": "Fájl feltöltő szolgáltatás",
"mKhgP9": "{n, plural, =0 {} =1 {zapp-olva} other {zapp-olva}}",
"mTJFgF": "Népszerű",
"mfe8RW": "Lehetőség: {n}",
"n1Whvj": "Váltás",
"nDejmx": "Tiltás visszavonása",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Langganan",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Gunakan koma untuk memisahkan kata, misalnya kata1, kata2, kata3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Nama pengguna",
"JGrt9q": "Kirim foto ke {name}",
"JHEHCk": "Zap ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Kedaluwarsa",
"RfhLwC": "Oleh: {author}",
"RhDAoS": "Anda yakin ingin menghapus {id}",
"RjpoYG": "Terbaru",
"RoOyAh": "Relai-relai",
"Rs4kCE": "Penanda buku",
"RwFaYs": "Urutkan",
"SLZGPn": "Masukkan pin untuk mengenkripsi kunci pribadi Anda, Anda harus memasukkan pin ini setiap kali Anda membuka {site}.",
"SMO+on": "Kirim zap ke {name}",
"SOqbe9": "Perbarui Alamat Petir",
@ -481,7 +480,6 @@
"mKAr6h": "Ikuti semua",
"mKh2HS": "Layanan unggah berkas",
"mKhgP9": "{n,plural,=0{} =1{di-zap} other{di-zap}}",
"mTJFgF": "Populer",
"mfe8RW": "Opsi: {n}",
"n1Whvj": "Beralih",
"nDejmx": "Buka blokir",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Abbonamenti",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Utilizzare le virgole per separare le parole, ad esempio parola1, parola2, parola3.",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Nome utente",
"JGrt9q": "Inviare saggi a {name}",
"JHEHCk": "({n}) Zap",
@ -282,10 +283,8 @@
"RahCRH": "Scaduto",
"RfhLwC": "Creato da: {author}",
"RhDAoS": "Vuoi davvero eliminare {id}?",
"RjpoYG": "Recente",
"RoOyAh": "Relay",
"Rs4kCE": "Preferito",
"RwFaYs": "Ordinamento",
"SLZGPn": "Inserire un pin per crittografare la chiave privata; questo pin deve essere inserito ogni volta che si apre {site}.",
"SMO+on": "Inviare zap a {name}",
"SOqbe9": "Aggiorna indirizzo Lightning",
@ -481,7 +480,6 @@
"mKAr6h": "Segui tutti",
"mKh2HS": "Servizio caricamento file",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Popolare",
"mfe8RW": "Opzione: {n}",
"n1Whvj": "Cambia",
"nDejmx": "Sblocca",

View File

@ -208,6 +208,7 @@
"J+dIsA": "サブスクリプション",
"J1iLmb": "通知を許可しない",
"J2HeQ+": "コンマで単語を区切るword1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "ユーザー名",
"JGrt9q": "satsを{name}送る",
"JHEHCk": "ザップ ({n})",
@ -282,10 +283,8 @@
"RahCRH": "失効",
"RfhLwC": "制作者: {author}",
"RhDAoS": "{id}を削除しますか?",
"RjpoYG": "最新",
"RoOyAh": "リレー",
"Rs4kCE": "ブックマーク",
"RwFaYs": "並び替え",
"SLZGPn": "秘密鍵を暗号化するためにピンを入力します。 {site}を開くたびにこのピンを入力する必要があります。",
"SMO+on": "ザップを{name}に送る",
"SOqbe9": "ライトニングアドレスの更新",
@ -481,7 +480,6 @@
"mKAr6h": "全てフォロー",
"mKh2HS": "ファイル添付サービス",
"mKhgP9": "{n,plural,=0{} =1{がザップしました} other{がザップしました}}",
"mTJFgF": "人気",
"mfe8RW": "オプション: {n}",
"n1Whvj": "切り替え",
"nDejmx": "ブロック解除",

View File

@ -208,6 +208,7 @@
"J+dIsA": "구독",
"J1iLmb": "허용되지 않는 알림",
"J2HeQ+": "쉼표를 사용하여 단어 구분(예: 단어1, 단어2, 단어3)",
"JA+tz3": "Looking up thread...",
"JCIgkj": "사용자 이름",
"JGrt9q": "{name}으로 수능 성적 보내기",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "만료됨",
"RfhLwC": "작성자: {author}",
"RhDAoS": "{id}삭제하시겠습니까?",
"RjpoYG": "최근",
"RoOyAh": "릴레이",
"Rs4kCE": "북마크",
"RwFaYs": "정렬",
"SLZGPn": "개인 키를 암호화하려면 핀을 입력하세요. {site}을 열 때마다 이 핀을 입력해야 합니다.",
"SMO+on": "{name}으로 zap 보내기",
"SOqbe9": "라이트닝 주소 업데이트",
@ -481,7 +480,6 @@
"mKAr6h": "모두 팔로우하기",
"mKh2HS": "파일 업로드 서비스",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "인기",
"mfe8RW": "옵션: {n}",
"n1Whvj": "스위치",
"nDejmx": "차단 해제",
@ -541,7 +539,7 @@
"u9NoC1": "이름은 {limit} 자 미만이어야 합니다.",
"uCk8r+": "이미 계정이 있으신가요?",
"uSV4Ti": "재게시물을 수동으로 확인해야 합니다.",
"uc0din": "수능 분할을 다음 주소로 전송합니다.",
"uc0din": "Sats을 다음 주소로 분할 전송합니다.",
"un1nGw": "{n} 노트",
"usAvMr": "프로필 수정",
"v8lolG": "채팅 시작",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Subscriptions",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Use commas to separate words e.g. word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Nama",
"JGrt9q": "Kirim sats ke {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Kedaluwarsa",
"RfhLwC": "Oleh: {author}",
"RhDAoS": "Anda yakin ingin memadam {id} ke?",
"RjpoYG": "Terbaru",
"RoOyAh": "relay-relay",
"Rs4kCE": "Penanda",
"RwFaYs": "Urut-kan",
"SLZGPn": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.",
"SMO+on": "Kirim zap ke {name}",
"SOqbe9": "Perbarui Alamat 'Lightning'",
@ -481,7 +480,6 @@
"mKAr6h": "Follow all",
"mKh2HS": "File upload service",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Popular",
"mfe8RW": "Option: {n}",
"n1Whvj": "Beralih",
"nDejmx": "Unblock",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Abonnementen",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Gebruik komma's om woorden te scheiden, bijv. woord1, woord2, woord3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Gebruikersnaam",
"JGrt9q": "Stuur sats naar {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Verlopen",
"RfhLwC": "Door: {author}",
"RhDAoS": "Weet u zeker dat u dit wilt verwijderen {id}",
"RjpoYG": "Recent",
"RoOyAh": "Relays",
"Rs4kCE": "Bladwijzers",
"RwFaYs": "Sorteer",
"SLZGPn": "Voer een pincode in om je privésleutel te coderen. Je moet deze pincode elke keer invoeren als je {site}opent.",
"SMO+on": "Stuur zap naar {name}",
"SOqbe9": "Update Lightning Adres",
@ -481,7 +480,6 @@
"mKAr6h": "Volg allen",
"mKh2HS": "File Upload service",
"mKhgP9": "{n,plural,one {}=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Populair",
"mfe8RW": "Optie: {n}",
"n1Whvj": "Wissel",
"nDejmx": "Deblokkeer",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Subscrições",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Use vírgulas para separar palavras, por exemplo, palavra1, palavra2, palavra3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Nome de usuário",
"JGrt9q": "Enviar sats para {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Expirado",
"RfhLwC": "Por: {author}",
"RhDAoS": "Tem certeza de que deseja excluir {id}",
"RjpoYG": "Recente",
"RoOyAh": "Relés",
"Rs4kCE": "Favoritar",
"RwFaYs": "Ordenar",
"SLZGPn": "Insira um PIN para criptografar sua chave privada. Você deve inserir esse PIN sempre que abrir o site {site}.",
"SMO+on": "Enviar zap para {name}",
"SOqbe9": "Atualizar endereço Lightning",
@ -481,7 +480,6 @@
"mKAr6h": "Seguir todos",
"mKh2HS": "Serviço de upload de arquivos",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Popular",
"mfe8RW": "Opção: {n}",
"n1Whvj": "Alternar",
"nDejmx": "Desbloquear",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Подписки",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Используйте запятые для разделения слов, например, слово1, слово2, слово3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Имя пользователя",
"JGrt9q": "Отправить sats на {name}",
"JHEHCk": "Запы ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Срок действия истёк",
"RfhLwC": "Автор: {author}",
"RhDAoS": "Вы уверены, что хотите удалить {id}",
"RjpoYG": "Недавние",
"RoOyAh": "Релеи",
"Rs4kCE": "Закладка",
"RwFaYs": "Сортировать",
"SLZGPn": "Введите пин-код для шифрования закрытого ключа, который необходимо вводить каждый раз, когда вы открываете сайт {site}.",
"SMO+on": "Отправить zap на {name}",
"SOqbe9": "Обновить лайтнинг-адрес",
@ -481,7 +480,6 @@
"mKAr6h": "Подписаться на всех",
"mKh2HS": "Служба загрузки файлов",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Популярное",
"mfe8RW": "Опция: {n}",
"n1Whvj": "Сменить",
"nDejmx": "Разблокировать",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Prenumerationer",
"J1iLmb": "Notiser inte tillåtna",
"J2HeQ+": "Använd kommatecken för att skilja ord åt, t.ex. ord1, ord2, ord3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Användarnamn",
"JGrt9q": "Skicka sats till {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Förfallen",
"RfhLwC": "Av: {author}",
"RhDAoS": "Är du säker på att du vill radera {id}",
"RjpoYG": "Senaste",
"RoOyAh": "Reläer",
"Rs4kCE": "Bokmärke",
"RwFaYs": "Sortera",
"SLZGPn": "Ange en pin för att kryptera din privata nyckel, du måste ange denna pin varje gång du öppnar {site}.",
"SMO+on": "Skicka zap till {name}",
"SOqbe9": "Uppdatera Lightning-adress",
@ -481,7 +480,6 @@
"mKAr6h": "Följ alla",
"mKh2HS": "Tjänst för filuppladdning",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Populärt",
"mfe8RW": "Alternativ: {n}",
"n1Whvj": "Växla",
"nDejmx": "Avblockera",

View File

@ -208,6 +208,7 @@
"J+dIsA": "Usajili",
"J1iLmb": "Arifa Haziruhusiwi",
"J2HeQ+": "Tumia koma kutenganisha maneno k.m. neno1, neno2, neno3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "Jina la mtumiaji",
"JGrt9q": "Tuma sats kwa {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "Muda wake umeisha",
"RfhLwC": "Na: {author}",
"RhDAoS": "Je, una uhakika unataka kufuta {id}",
"RjpoYG": "Hivi karibuni",
"RoOyAh": "Relays",
"Rs4kCE": "Alamisho",
"RwFaYs": "Panga",
"SLZGPn": "Ingiza pin kuweka funguo yako binafsi, unapaswa kuingiza pin hii kila wakati unapofungua {site}.",
"SMO+on": "Tuma zap kwa {name}",
"SOqbe9": "Sasisha Anwani ya Umeme",
@ -481,7 +480,6 @@
"mKAr6h": "Fuata wote",
"mKh2HS": "Huduma ya kupakia faili",
"mKhgP9": "{n,plural,one {}=0{} =1{zapped} other{zapped}}",
"mTJFgF": "Maarufu",
"mfe8RW": "Chaguo: {n}",
"n1Whvj": "Badili",
"nDejmx": "Ondoa kizuizi",

View File

@ -208,6 +208,7 @@
"J+dIsA": "சந்தாக்கள்",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "சொற்களைப் பிரிக்க காற்புள்ளிகளைப் பயன்படுத்தவும் எ.கா. சொல்1, சொல்2, சொல்3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "பயனர் பெயர்",
"JGrt9q": "{name} க்கு சாட்களை அனுப்பு",
"JHEHCk": "ஜாப்கள் ({n})",
@ -282,10 +283,8 @@
"RahCRH": "காலாவதியாகிவிட்டது",
"RfhLwC": "எழுதியவர்: {author}",
"RhDAoS": "{id} ஐ நிச்சயமாக நீக்க விரும்புகிறீர்களா",
"RjpoYG": "அண்மை",
"RoOyAh": "ரிலேகள்",
"Rs4kCE": "புக்மார்க்",
"RwFaYs": "வரிசைப்படுத்துக",
"SLZGPn": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.",
"SMO+on": "Send zap to {name}",
"SOqbe9": "லைட்னிங் முகவரியை உள்ளிடவும்",
@ -481,7 +480,6 @@
"mKAr6h": "அனைத்தையும் பின்பற்றவும்",
"mKh2HS": "கோப்பு பதிவேற்ற சேவை",
"mKhgP9": "{n,plural,=0{} =1{ஜாப் செய்தார்} other{ஜாப் செய்தனர்}}",
"mTJFgF": "Popular",
"mfe8RW": "விருப்பம்: {n}",
"n1Whvj": "மாற்று",
"nDejmx": "முடக்கத்தை நீக்கு",

View File

@ -208,6 +208,7 @@
"J+dIsA": "การสมัครสมาชิก",
"J1iLmb": "Notifications Not Allowed",
"J2HeQ+": "Use commas to separate words e.g. word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "ชื่อผู้ใช้",
"JGrt9q": "Send sats to {name}",
"JHEHCk": "Zaps ({n})",
@ -282,10 +283,8 @@
"RahCRH": "หมดอายุแล้ว",
"RfhLwC": "โดย {author}",
"RhDAoS": "คุณแน่ใจหรือไม่ ว่าต้องการลบ {id}",
"RjpoYG": "เมื่อเร็ว ๆ นี้",
"RoOyAh": "รีเลย์",
"Rs4kCE": "บุ๊คมาร์ก",
"RwFaYs": "การจัดเรียง",
"SLZGPn": "Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.",
"SMO+on": "Send zap to {name}",
"SOqbe9": "อัพเดต Lightning Address",
@ -481,7 +480,6 @@
"mKAr6h": "ติดตามทั้งหมด",
"mKh2HS": "บริการอัพโหลดไฟล์",
"mKhgP9": "{n,plural,=0{} =1{zapped} other{zapped}}",
"mTJFgF": "ยอดนิยม",
"mfe8RW": "ตัวเลือก: {n}",
"n1Whvj": "สลับ",
"nDejmx": "ยกเลิกการบล็อค",

View File

@ -208,6 +208,7 @@
"J+dIsA": "订阅",
"J1iLmb": "未允许通知",
"J2HeQ+": "使用逗号分隔单词,如 word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "用户名",
"JGrt9q": "将聪发送到 {name}",
"JHEHCk": "打闪 ({n})",
@ -282,10 +283,8 @@
"RahCRH": "已过期",
"RfhLwC": "作者:{author}",
"RhDAoS": "是否确定要删除 {id}",
"RjpoYG": "最新",
"RoOyAh": "中继器",
"Rs4kCE": "收藏",
"RwFaYs": "排序",
"SLZGPn": "输入密码来加密私人密钥,每次打开 {site}时都必须输入该密码。",
"SMO+on": "将打闪发送到 {name}",
"SOqbe9": "更新闪电地址",
@ -481,7 +480,6 @@
"mKAr6h": "关注所有",
"mKh2HS": "文件上传服务",
"mKhgP9": "{n,plural,=0{} =1{已打闪} other{已打闪}}",
"mTJFgF": "热门",
"mfe8RW": "选项:{n}",
"n1Whvj": "切换",
"nDejmx": "解除屏蔽",

View File

@ -208,6 +208,7 @@
"J+dIsA": "訂閱",
"J1iLmb": "未允許通知",
"J2HeQ+": "使用逗号分隔单词,如 word1, word2, word3",
"JA+tz3": "Looking up thread...",
"JCIgkj": "用戶名",
"JGrt9q": "將聰發送到 {name}",
"JHEHCk": "打閃({n}",
@ -282,10 +283,8 @@
"RahCRH": "已過期",
"RfhLwC": "作者:{author}",
"RhDAoS": "是否確定要刪除 {id}",
"RjpoYG": "最新",
"RoOyAh": "中繼器",
"Rs4kCE": "收藏",
"RwFaYs": "排序",
"SLZGPn": "輸入一個 PIN 碼來加密你的私鑰,每次開啟 {site} 時都必須輸入此 PIN 碼。",
"SMO+on": "將打閃發送到 {name}",
"SOqbe9": "更新閃電地址",
@ -481,7 +480,6 @@
"mKAr6h": "全部關注",
"mKh2HS": "文件上傳服務",
"mKhgP9": "{n,plural,=0{} =1{已打閃} other{已打閃}}",
"mTJFgF": "熱門",
"mfe8RW": "選項:{n}",
"n1Whvj": "切換",
"nDejmx": "解除屏蔽",

View File

@ -287,7 +287,7 @@ export class NostrSystem extends EventEmitter<NostrSystemEvents> implements Syst
for (const list of this.userFollowsCache.snapshot()) {
const user = ID(list.pubkey);
for (const fx of list.follows) {
if (fx[0] === "p" && fx[1].length === 64) {
if (fx[0] === "p" && fx[1]?.length === 64) {
socialGraphInstance.addFollower(ID(fx[1]), user);
}
}

View File

@ -1,11 +1,4 @@
import {
EventMetadata,
NostrEvent,
OkResponse,
ReqCommand,
WorkerMessage,
WorkerMessageCommand,
} from "./types";
import { EventMetadata, NostrEvent, OkResponse, ReqCommand, WorkerMessage, WorkerMessageCommand } from "./types";
import { v4 as uuid } from "uuid";
export class WorkerRelayInterface {