refactor: improve whitelabel config
Some checks failed
continuous-integration/drone/push Build is failing
@ -4,8 +4,7 @@
|
|||||||
"appTitle": "Snort - Nostr",
|
"appTitle": "Snort - Nostr",
|
||||||
"hostname": "snort.social",
|
"hostname": "snort.social",
|
||||||
"nip05Domain": "snort.social",
|
"nip05Domain": "snort.social",
|
||||||
"favicon": "public/favicon.ico",
|
"icon": "/nostrich_512.png",
|
||||||
"appleTouchIconUrl": "/nostrich_512.png",
|
|
||||||
"navLogo": null,
|
"navLogo": null,
|
||||||
"publicDir": "public/snort",
|
"publicDir": "public/snort",
|
||||||
"httpCache": "",
|
"httpCache": "",
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
"appTitle": "iris",
|
"appTitle": "iris",
|
||||||
"hostname": "iris.to",
|
"hostname": "iris.to",
|
||||||
"nip05Domain": "iris.to",
|
"nip05Domain": "iris.to",
|
||||||
"favicon": "public/iris/favicon.ico",
|
"icon": "/img/icon128.png",
|
||||||
"appleTouchIconUrl": "/img/apple-touch-icon.png",
|
|
||||||
"navLogo": "/img/icon128.png",
|
"navLogo": "/img/icon128.png",
|
||||||
"publicDir": "public/iris",
|
"publicDir": "public/iris",
|
||||||
"httpCache": "",
|
"httpCache": "",
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
"appTitle": "Nostr",
|
"appTitle": "Nostr",
|
||||||
"hostname": "nostr.com",
|
"hostname": "nostr.com",
|
||||||
"nip05Domain": "nostr.com",
|
"nip05Domain": "nostr.com",
|
||||||
"favicon": "public/favicon.ico",
|
"icon": "/nostr.jpg",
|
||||||
"appleTouchIconUrl": "/nostrich_512.png",
|
|
||||||
"navLogo": null,
|
"navLogo": null,
|
||||||
"publicDir": "public/snort",
|
"publicDir": "public/nostr",
|
||||||
"httpCache": "",
|
"httpCache": "",
|
||||||
"animalNamePlaceholders": false,
|
"animalNamePlaceholders": false,
|
||||||
"features": {
|
"features": {
|
||||||
@ -40,6 +39,7 @@
|
|||||||
"defaultRelays": {
|
"defaultRelays": {
|
||||||
"wss://relay.snort.social/": { "read": true, "write": true },
|
"wss://relay.snort.social/": { "read": true, "write": true },
|
||||||
"wss://nostr.wine/": { "read": true, "write": false },
|
"wss://nostr.wine/": { "read": true, "write": false },
|
||||||
"wss://eden.nostr.land/": { "read": true, "write": false }
|
"wss://eden.nostr.land/": { "read": true, "write": false },
|
||||||
|
"wss://nos.lol/": { "read": true, "write": true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
packages/app/custom.d.ts
vendored
@ -47,8 +47,7 @@ declare const CONFIG: {
|
|||||||
appTitle: string;
|
appTitle: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
nip05Domain: string;
|
nip05Domain: string;
|
||||||
favicon: string;
|
icon: string;
|
||||||
appleTouchIconUrl: string;
|
|
||||||
navLogo: string | null;
|
navLogo: string | null;
|
||||||
httpCache: string;
|
httpCache: string;
|
||||||
animalNamePlaceholders: boolean;
|
animalNamePlaceholders: boolean;
|
||||||
|
@ -11,10 +11,12 @@
|
|||||||
name="keywords"
|
name="keywords"
|
||||||
content="nostr snort fast decentralized social media censorship resistant open source software" />
|
content="nostr snort fast decentralized social media censorship resistant open source software" />
|
||||||
<link rel="preconnect" href="https://imgproxy.snort.social" />
|
<link rel="preconnect" href="https://imgproxy.snort.social" />
|
||||||
<link rel="apple-touch-icon" href="" />
|
<link rel="apple-touch-icon" href="/img/apple-touch-icon.png" />
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<link rel="icon" href="/favicon.png" />
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/index.tsx"></script>
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
Before Width: | Height: | Size: 15 KiB |
BIN
packages/app/public/iris/favicon.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
packages/app/public/nostr/favicon.png
Normal file
After Width: | Height: | Size: 165 B |
BIN
packages/app/public/nostr/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 405 B |
BIN
packages/app/public/nostr/nostr.jpg
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
packages/app/public/snort/favicon.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
packages/app/public/snort/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 44 KiB |
29
packages/app/src/Hooks/useEmptyChatSystem.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { unwrap } from "@snort/shared";
|
||||||
|
import { decodeTLV, EventKind, RequestBuilder, TLVEntryType } from "@snort/system";
|
||||||
|
import { useRequestBuilder } from "@snort/system-react";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
import { createEmptyChatObject } from "@/chat";
|
||||||
|
|
||||||
|
export function useEmptyChatSystem(id?: string) {
|
||||||
|
const sub = useMemo(() => {
|
||||||
|
if (!id) return;
|
||||||
|
|
||||||
|
if (id.startsWith("chat281")) {
|
||||||
|
const cx = unwrap(decodeTLV(id).find(a => a.type === TLVEntryType.Special)).value as string;
|
||||||
|
const rb = new RequestBuilder(`nip28:${id}`);
|
||||||
|
rb.withFilter().ids([cx]).kinds([EventKind.PublicChatChannel, EventKind.PublicChatMetadata]);
|
||||||
|
rb.withFilter()
|
||||||
|
.tag("e", [cx])
|
||||||
|
.kinds([EventKind.PublicChatChannel, EventKind.PublicChatMessage, EventKind.PublicChatMetadata]);
|
||||||
|
|
||||||
|
return rb;
|
||||||
|
}
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const data = useRequestBuilder(sub);
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!id) return;
|
||||||
|
return createEmptyChatObject(id, data);
|
||||||
|
}, [id, data.length]);
|
||||||
|
}
|
@ -12,6 +12,7 @@ import Modal from "@/Components/Modal/Modal";
|
|||||||
import QrCode from "@/Components/QrCode";
|
import QrCode from "@/Components/QrCode";
|
||||||
import ProfilePreview from "@/Components/User/ProfilePreview";
|
import ProfilePreview from "@/Components/User/ProfilePreview";
|
||||||
import SnortApi, { RevenueSplit, RevenueToday } from "@/External/SnortApi";
|
import SnortApi, { RevenueSplit, RevenueToday } from "@/External/SnortApi";
|
||||||
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import { bech32ToHex, unwrap } from "@/Utils";
|
import { bech32ToHex, unwrap } from "@/Utils";
|
||||||
import { ApiHost, DeveloperAccounts, SnortPubKey } from "@/Utils/Const";
|
import { ApiHost, DeveloperAccounts, SnortPubKey } from "@/Utils/Const";
|
||||||
import { ZapPoolController, ZapPoolRecipientType } from "@/Utils/ZapPoolController";
|
import { ZapPoolController, ZapPoolRecipientType } from "@/Utils/ZapPoolController";
|
||||||
@ -67,6 +68,7 @@ const DonatePage = () => {
|
|||||||
const [onChain, setOnChain] = useState("");
|
const [onChain, setOnChain] = useState("");
|
||||||
const api = new SnortApi(ApiHost);
|
const api = new SnortApi(ApiHost);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const login = useLogin();
|
||||||
|
|
||||||
async function getOnChainAddress() {
|
async function getOnChainAddress() {
|
||||||
const { address } = await api.onChainDonation();
|
const { address } = await api.onChainDonation();
|
||||||
@ -153,9 +155,10 @@ const DonatePage = () => {
|
|||||||
return (
|
return (
|
||||||
<AsyncButton
|
<AsyncButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(`/messages/${Nip28ChatSystem.chatId(a.value)}`);
|
const id = Nip28ChatSystem.chatId(a.value);
|
||||||
|
navigate(`/messages/${id}`);
|
||||||
}}>
|
}}>
|
||||||
<img src={CONFIG.appleTouchIconUrl} width={24} height={24} className="rounded-full" />
|
<img src={CONFIG.icon} width={24} height={24} className="rounded-full" />
|
||||||
<FormattedMessage defaultMessage="Nostr Public Chat" id="whSrs+" />
|
<FormattedMessage defaultMessage="Nostr Public Chat" id="whSrs+" />
|
||||||
</AsyncButton>
|
</AsyncButton>
|
||||||
);
|
);
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useMemo } from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import { Chat, createEmptyChatObject, useChatSystem } from "@/chat";
|
import { Chat, useChat } from "@/chat";
|
||||||
import ProfileImage from "@/Components/User/ProfileImage";
|
import ProfileImage from "@/Components/User/ProfileImage";
|
||||||
import useLogin from "@/Hooks/useLogin";
|
|
||||||
import DM from "@/Pages/Messages/DM";
|
import DM from "@/Pages/Messages/DM";
|
||||||
import WriteMessage from "@/Pages/Messages/WriteMessage";
|
import WriteMessage from "@/Pages/Messages/WriteMessage";
|
||||||
|
|
||||||
import { ChatParticipantProfile } from "./ChatParticipant";
|
import { ChatParticipantProfile } from "./ChatParticipant";
|
||||||
|
|
||||||
export default function DmWindow({ id }: { id: string }) {
|
export default function DmWindow({ id }: { id: string }) {
|
||||||
const dms = useChatSystem();
|
const chat = useChat(id);
|
||||||
const chat = dms.find(a => a.id === id) ?? createEmptyChatObject(id);
|
|
||||||
|
|
||||||
function sender() {
|
function sender() {
|
||||||
|
if (!chat) return;
|
||||||
if (chat.participants.length === 1) {
|
if (chat.participants.length === 1) {
|
||||||
return <ChatParticipantProfile participant={chat.participants[0]} />;
|
return <ChatParticipantProfile participant={chat.participants[0]} />;
|
||||||
} else {
|
} else {
|
||||||
@ -29,63 +28,28 @@ export default function DmWindow({ id }: { id: string }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-1 flex-col h-[calc(100vh-62px)] md:h-screen">
|
<div className="flex flex-1 flex-col h-full w-full md:h-screen">
|
||||||
<div className="p-3">{sender()}</div>
|
<div className="p-3">{sender()}</div>
|
||||||
<div className="overflow-y-auto hide-scrollbar p-2.5 flex-grow">
|
<div className="overflow-y-auto hide-scrollbar p-2.5 flex-grow">{chat && <DmChatSelected chat={chat} />}</div>
|
||||||
<div className="flex flex-col">{chat && <DmChatSelected chat={chat} />}</div>
|
<div className="flex items-center gap-2.5 p-2.5">{chat && <WriteMessage chat={chat} />}</div>
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2.5 p-2.5">
|
|
||||||
<WriteMessage chat={chat} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DmChatSelected({ chat }: { chat: Chat }) {
|
function DmChatSelected({ chat }: { chat: Chat }) {
|
||||||
const { publicKey: myPubKey } = useLogin(s => ({ publicKey: s.publicKey }));
|
|
||||||
const messagesContainerRef = useRef<HTMLDivElement>(null);
|
|
||||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
const sortedDms = useMemo(() => {
|
const sortedDms = useMemo(() => {
|
||||||
const myDms = chat?.messages;
|
const myDms = chat?.messages;
|
||||||
if (myPubKey && myDms) {
|
if (myDms) {
|
||||||
// filter dms in this chat, or dms to self
|
return [...myDms].sort((a, b) => (a.created_at > b.created_at ? -1 : 1));
|
||||||
return [...myDms].sort((a, b) => a.created_at - b.created_at);
|
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}, [chat, myPubKey]);
|
}, [chat]);
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
|
||||||
messagesEndRef.current?.scrollIntoView({ behavior: "instant" });
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const observer = new ResizeObserver(() => {
|
|
||||||
scrollToBottom();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start observing the element that you want to keep in view
|
|
||||||
if (messagesContainerRef.current) {
|
|
||||||
observer.observe(messagesContainerRef.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to scroll to bottom on initial load
|
|
||||||
scrollToBottom();
|
|
||||||
|
|
||||||
// Clean up the observer on component unmount
|
|
||||||
return () => {
|
|
||||||
if (messagesContainerRef.current) {
|
|
||||||
observer.unobserve(messagesContainerRef.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [sortedDms]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col" ref={messagesContainerRef}>
|
<div className="flex flex-col-reverse">
|
||||||
{sortedDms.map(a => (
|
{sortedDms.map(a => (
|
||||||
<DM data={a} key={a.id} chat={chat} />
|
<DM data={a} key={a.id} chat={chat} />
|
||||||
))}
|
))}
|
||||||
<div ref={messagesEndRef} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
|
||||||
@ -13,7 +13,6 @@ import { ChatParticipantProfile } from "@/Pages/Messages/ChatParticipant";
|
|||||||
import DmWindow from "@/Pages/Messages/DmWindow";
|
import DmWindow from "@/Pages/Messages/DmWindow";
|
||||||
import NewChatWindow from "@/Pages/Messages/NewChatWindow";
|
import NewChatWindow from "@/Pages/Messages/NewChatWindow";
|
||||||
import UnreadCount from "@/Pages/Messages/UnreadCount";
|
import UnreadCount from "@/Pages/Messages/UnreadCount";
|
||||||
import { parseId } from "@/Utils";
|
|
||||||
|
|
||||||
const TwoCol = 768;
|
const TwoCol = 768;
|
||||||
|
|
||||||
@ -22,13 +21,8 @@ export default function MessagesPage() {
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [chat, setChat] = useState<string>();
|
|
||||||
const pageWidth = usePageWidth();
|
const pageWidth = usePageWidth();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const parsedId = parseId(id ?? "");
|
|
||||||
setChat(id ? parsedId : undefined);
|
|
||||||
}, [id]);
|
|
||||||
const chats = useChatSystem();
|
const chats = useChatSystem();
|
||||||
|
|
||||||
const unreadCount = useMemo(() => chats.reduce((p, c) => p + c.unread, 0), [chats]);
|
const unreadCount = useMemo(() => chats.reduce((p, c) => p + c.unread, 0), [chats]);
|
||||||
@ -67,7 +61,7 @@ export default function MessagesPage() {
|
|||||||
const participants = cx.participants.map(a => a.id);
|
const participants = cx.participants.map(a => a.id);
|
||||||
if (participants.length === 1 && participants[0] === login.publicKey) return noteToSelf(cx);
|
if (participants.length === 1 && participants[0] === login.publicKey) return noteToSelf(cx);
|
||||||
|
|
||||||
const isActive = cx.id === chat;
|
const isActive = cx.id === id;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classNames("flex items-center p cursor-pointer justify-between", { active: isActive })}
|
className={classNames("flex items-center p cursor-pointer justify-between", { active: isActive })}
|
||||||
@ -89,7 +83,7 @@ export default function MessagesPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-1 md:h-screen md:overflow-hidden">
|
<div className="flex flex-1 md:h-screen md:overflow-hidden">
|
||||||
{(pageWidth >= TwoCol || !chat) && (
|
{pageWidth >= TwoCol && !id && (
|
||||||
<div className="overflow-y-auto md:h-screen p-1 w-full md:w-1/3 flex-shrink-0">
|
<div className="overflow-y-auto md:h-screen p-1 w-full md:w-1/3 flex-shrink-0">
|
||||||
<div className="flex items-center justify-between p-2">
|
<div className="flex items-center justify-between p-2">
|
||||||
<button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold">
|
<button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold">
|
||||||
@ -109,7 +103,7 @@ export default function MessagesPage() {
|
|||||||
.map(conversation)}
|
.map(conversation)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{chat ? <DmWindow id={chat} /> : pageWidth >= TwoCol && <div className="flex-1 rt-border"></div>}
|
{id ? <DmWindow id={id} /> : pageWidth >= TwoCol && <div className="flex-1 rt-border"></div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ export function SignIn() {
|
|||||||
const nip7Login = hasNip7 && !useKey;
|
const nip7Login = hasNip7 && !useKey;
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col g24">
|
<div className="flex flex-col g24">
|
||||||
<img src={CONFIG.appleTouchIconUrl} width={48} height={48} className="br mr-auto ml-auto" />
|
<img src={CONFIG.icon} width={48} height={48} className="br mr-auto ml-auto" />
|
||||||
<div className="flex flex-col g16 items-center">
|
<div className="flex flex-col g16 items-center">
|
||||||
<h1>
|
<h1>
|
||||||
<FormattedMessage defaultMessage="Sign In" id="Ub+AGc" />
|
<FormattedMessage defaultMessage="Sign In" id="Ub+AGc" />
|
||||||
@ -152,7 +152,7 @@ export function SignUp() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col g24">
|
<div className="flex flex-col g24">
|
||||||
<img src={CONFIG.appleTouchIconUrl} width={48} height={48} className="br mr-auto ml-auto" />
|
<img src={CONFIG.icon} width={48} height={48} className="br mr-auto ml-auto" />
|
||||||
<div className="flex flex-col g16 items-center">
|
<div className="flex flex-col g16 items-center">
|
||||||
<h1>
|
<h1>
|
||||||
<FormattedMessage defaultMessage="Sign Up" id="39AHJm" />
|
<FormattedMessage defaultMessage="Sign Up" id="39AHJm" />
|
||||||
|
@ -15,6 +15,7 @@ import {
|
|||||||
import { useSyncExternalStore } from "react";
|
import { useSyncExternalStore } from "react";
|
||||||
|
|
||||||
import { Chats, GiftsCache } from "@/Cache";
|
import { Chats, GiftsCache } from "@/Cache";
|
||||||
|
import { useEmptyChatSystem } from "@/Hooks/useEmptyChatSystem";
|
||||||
import useLogin from "@/Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import useModeration from "@/Hooks/useModeration";
|
import useModeration from "@/Hooks/useModeration";
|
||||||
import { findTag } from "@/Utils";
|
import { findTag } from "@/Utils";
|
||||||
@ -155,15 +156,15 @@ export function createChatLink(type: ChatType, ...params: Array<string>) {
|
|||||||
throw new Error("Unknown chat type");
|
throw new Error("Unknown chat type");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createEmptyChatObject(id: string) {
|
export function createEmptyChatObject(id: string, messages?: Array<TaggedNostrEvent>) {
|
||||||
if (id.startsWith("chat41")) {
|
if (id.startsWith("chat41")) {
|
||||||
return Nip4ChatSystem.createChatObj(id, []);
|
return Nip4ChatSystem.createChatObj(id, messages ?? []);
|
||||||
}
|
}
|
||||||
if (id.startsWith("chat241")) {
|
if (id.startsWith("chat241")) {
|
||||||
return Nip24ChatSystem.createChatObj(id, []);
|
return Nip24ChatSystem.createChatObj(id, []);
|
||||||
}
|
}
|
||||||
if (id.startsWith("chat281")) {
|
if (id.startsWith("chat281")) {
|
||||||
return Nip28ChatSystem.createChatObj(id, []);
|
return Nip28ChatSystem.createChatObj(id, messages ?? []);
|
||||||
}
|
}
|
||||||
throw new Error("Cant create new empty chat, unknown id");
|
throw new Error("Cant create new empty chat, unknown id");
|
||||||
}
|
}
|
||||||
@ -209,3 +210,24 @@ export function useChatSystem() {
|
|||||||
return authors.length === 0 || !authors.every(a => isBlocked(a));
|
return authors.length === 0 || !authors.every(a => isBlocked(a));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useChat(id: string) {
|
||||||
|
const getStore = () => {
|
||||||
|
if (id.startsWith("chat41")) {
|
||||||
|
return Nip4Chats;
|
||||||
|
}
|
||||||
|
if (id.startsWith("chat281")) {
|
||||||
|
return Nip28Chats;
|
||||||
|
}
|
||||||
|
throw new Error("Unsupported chat system");
|
||||||
|
};
|
||||||
|
const store = getStore();
|
||||||
|
const ret = useSyncExternalStore(
|
||||||
|
c => store.hook(c),
|
||||||
|
() => {
|
||||||
|
return store.snapshot().find(a => a.id === id);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const emptyChat = useEmptyChatSystem(ret === undefined ? id : undefined);
|
||||||
|
return ret ?? emptyChat;
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ import "./index.css";
|
|||||||
import "@szhsin/react-menu/dist/index.css";
|
import "@szhsin/react-menu/dist/index.css";
|
||||||
import "@/assets/fonts/inter.css";
|
import "@/assets/fonts/inter.css";
|
||||||
|
|
||||||
import { encodeTLVEntries, socialGraphInstance } from "@snort/system";
|
import { socialGraphInstance } from "@snort/system";
|
||||||
import { SnortContext } from "@snort/system-react";
|
import { SnortContext } from "@snort/system-react";
|
||||||
import { StrictMode } from "react";
|
import { StrictMode } from "react";
|
||||||
import * as ReactDOM from "react-dom/client";
|
import * as ReactDOM from "react-dom/client";
|
||||||
@ -34,6 +34,9 @@ import { RootTabRoutes } from "@/Pages/Root/RootTabRoutes";
|
|||||||
import SearchPage from "@/Pages/SearchPage";
|
import SearchPage from "@/Pages/SearchPage";
|
||||||
import SettingsRoutes from "@/Pages/settings/Routes";
|
import SettingsRoutes from "@/Pages/settings/Routes";
|
||||||
import { SubscribeRoutes } from "@/Pages/subscribe";
|
import { SubscribeRoutes } from "@/Pages/subscribe";
|
||||||
|
import WalletPage from "@/Pages/wallet";
|
||||||
|
import { WalletReceivePage } from "@/Pages/wallet/receive";
|
||||||
|
import { WalletSendPage } from "@/Pages/wallet/send";
|
||||||
import ZapPoolPage from "@/Pages/ZapPool";
|
import ZapPoolPage from "@/Pages/ZapPool";
|
||||||
import { System } from "@/system";
|
import { System } from "@/system";
|
||||||
import { storeRefCode, unwrap } from "@/Utils";
|
import { storeRefCode, unwrap } from "@/Utils";
|
||||||
@ -42,10 +45,6 @@ import { hasWasm, wasmInit, WasmPath } from "@/Utils/wasm";
|
|||||||
import { Wallets } from "@/Wallet";
|
import { Wallets } from "@/Wallet";
|
||||||
import { setupWebLNWalletConfig } from "@/Wallet/WebLN";
|
import { setupWebLNWalletConfig } from "@/Wallet/WebLN";
|
||||||
|
|
||||||
import WalletPage from "./Pages/wallet";
|
|
||||||
import { WalletReceivePage } from "./Pages/wallet/receive";
|
|
||||||
import { WalletSendPage } from "./Pages/wallet/send";
|
|
||||||
|
|
||||||
async function initSite() {
|
async function initSite() {
|
||||||
storeRefCode();
|
storeRefCode();
|
||||||
if (hasWasm) {
|
if (hasWasm) {
|
||||||
@ -222,10 +221,5 @@ root.render(
|
|||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
//@ts-ignore
|
|
||||||
window.encodeTLV = encodeTLVEntries;
|
|
||||||
|
|
||||||
// Use react-helmet instead?
|
// Use react-helmet instead?
|
||||||
document.title = CONFIG.appTitle;
|
document.title = CONFIG.appTitle;
|
||||||
document.querySelector('link[rel="apple-touch-icon"]')?.setAttribute("href", CONFIG.appleTouchIconUrl);
|
|
||||||
|
@ -272,7 +272,6 @@ function makeNotification(n: PushNotification) {
|
|||||||
const ret = {
|
const ret = {
|
||||||
body: body(),
|
body: body(),
|
||||||
icon: evx.author.avatar ?? defaultAvatar(evx.author.pubkey),
|
icon: evx.author.avatar ?? defaultAvatar(evx.author.pubkey),
|
||||||
badge: `${location.protocol}//${location.hostname}${CONFIG.appleTouchIconUrl}`,
|
|
||||||
timestamp: evx.created_at * 1000,
|
timestamp: evx.created_at * 1000,
|
||||||
tag: evx.id,
|
tag: evx.id,
|
||||||
data: JSON.stringify(n),
|
data: JSON.stringify(n),
|
||||||
|