chore: follow snort for new keys
This commit is contained in:
parent
de5700f423
commit
ec28a51148
@ -20,6 +20,11 @@ export const VoidCatHost = "https://void.cat";
|
|||||||
*/
|
*/
|
||||||
export const KieranPubKey = "npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49";
|
export const KieranPubKey = "npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Official snort account
|
||||||
|
*/
|
||||||
|
export const SnortPubKey = "npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Websocket re-connect timeout
|
* Websocket re-connect timeout
|
||||||
*/
|
*/
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ApiHost, KieranPubKey } from "Const";
|
import { ApiHost, KieranPubKey, SnortPubKey } from "Const";
|
||||||
import ProfilePreview from "Element/ProfilePreview";
|
import ProfilePreview from "Element/ProfilePreview";
|
||||||
import ZapButton from "Element/ZapButton";
|
import ZapButton from "Element/ZapButton";
|
||||||
import { HexKey } from "Nostr";
|
import { HexKey } from "Nostr";
|
||||||
@ -72,7 +72,7 @@ const DonatePage = () => {
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="mr10">Lightning Donation: </div>
|
<div className="mr10">Lightning Donation: </div>
|
||||||
<ZapButton
|
<ZapButton
|
||||||
pubkey={"84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864"}
|
pubkey={bech32ToHex(SnortPubKey)}
|
||||||
svc={"donate@snort.social"}
|
svc={"donate@snort.social"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,32 +7,25 @@ import Bell from "Icons/Bell";
|
|||||||
import Search from "Icons/Search";
|
import Search from "Icons/Search";
|
||||||
|
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import { init, UserPreferences } from "State/Login";
|
import { init, setRelays } from "State/Login";
|
||||||
import { HexKey, RawEvent, TaggedRawEvent } from "Nostr";
|
|
||||||
import { RelaySettings } from "Nostr/Connection";
|
|
||||||
import { System } from "Nostr/System"
|
import { System } from "Nostr/System"
|
||||||
import ProfileImage from "Element/ProfileImage";
|
import ProfileImage from "Element/ProfileImage";
|
||||||
import useLoginFeed from "Feed/LoginFeed";
|
import useLoginFeed from "Feed/LoginFeed";
|
||||||
import { totalUnread } from "Pages/MessagesPage";
|
import { totalUnread } from "Pages/MessagesPage";
|
||||||
import { SearchRelays } from 'Const';
|
import { SearchRelays, SnortPubKey } from 'Const';
|
||||||
import useEventPublisher from "Feed/EventPublisher";
|
import useEventPublisher from "Feed/EventPublisher";
|
||||||
import useModeration from "Hooks/useModeration";
|
import useModeration from "Hooks/useModeration";
|
||||||
import { IndexedUDB, useDb } from "State/Users/Db";
|
import { IndexedUDB, useDb } from "State/Users/Db";
|
||||||
import { db } from "Db";
|
import { db } from "Db";
|
||||||
|
import { bech32ToHex } from "Util";
|
||||||
|
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isInit = useSelector<RootState, boolean | undefined>(s => s.login.loggedOut);
|
const { loggedOut, publicKey, relays, notifications, readNotifications, dms, preferences, newUserKey } = useSelector((s: RootState) => s.login);
|
||||||
const key = useSelector<RootState, HexKey | undefined>(s => s.login.publicKey);
|
|
||||||
const relays = useSelector<RootState, Record<string, RelaySettings>>(s => s.login.relays);
|
|
||||||
const notifications = useSelector<RootState, TaggedRawEvent[]>(s => s.login.notifications);
|
|
||||||
const readNotifications = useSelector<RootState, number>(s => s.login.readNotifications);
|
|
||||||
const dms = useSelector<RootState, RawEvent[]>(s => s.login.dms);
|
|
||||||
const { isMuted } = useModeration();
|
const { isMuted } = useModeration();
|
||||||
const filteredDms = dms.filter(a => !isMuted(a.pubkey))
|
const filteredDms = dms.filter(a => !isMuted(a.pubkey))
|
||||||
const prefs = useSelector<RootState, UserPreferences>(s => s.login.preferences);
|
|
||||||
const usingDb = useDb();
|
const usingDb = useDb();
|
||||||
const pub = useEventPublisher();
|
const pub = useEventPublisher();
|
||||||
useLoginFeed();
|
useLoginFeed();
|
||||||
@ -69,15 +62,15 @@ export default function Layout() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let osTheme = window.matchMedia("(prefers-color-scheme: light)");
|
let osTheme = window.matchMedia("(prefers-color-scheme: light)");
|
||||||
setTheme(prefs.theme === "system" && osTheme.matches ? "light" : prefs.theme === "light" ? "light" : "dark");
|
setTheme(preferences.theme === "system" && osTheme.matches ? "light" : preferences.theme === "light" ? "light" : "dark");
|
||||||
|
|
||||||
osTheme.onchange = (e) => {
|
osTheme.onchange = (e) => {
|
||||||
if (prefs.theme === "system") {
|
if (preferences.theme === "system") {
|
||||||
setTheme(e.matches ? "light" : "dark");
|
setTheme(e.matches ? "light" : "dark");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return () => { osTheme.onchange = null; }
|
return () => { osTheme.onchange = null; }
|
||||||
}, [prefs.theme]);
|
}, [preferences.theme]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// check DB support then init
|
// check DB support then init
|
||||||
@ -104,6 +97,33 @@ export default function Layout() {
|
|||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
async function handleNewUser() {
|
||||||
|
try {
|
||||||
|
let rsp = await fetch("https://api.nostr.watch/v1/online");
|
||||||
|
if (rsp.ok) {
|
||||||
|
let online: string[] = await rsp.json();
|
||||||
|
let pickRandom = online.sort((a, b) => Math.random() >= 0.5 ? 1 : -1).slice(0, 4); // pick 4 random relays
|
||||||
|
|
||||||
|
let relayObjects = pickRandom.map(a => [a, { read: true, write: true }]);
|
||||||
|
dispatch(setRelays({
|
||||||
|
relays: Object.fromEntries(relayObjects),
|
||||||
|
createdAt: 1
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ev = await pub.addFollow(bech32ToHex(SnortPubKey));
|
||||||
|
pub.broadcast(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (newUserKey === true) {
|
||||||
|
handleNewUser().catch(console.warn);
|
||||||
|
}
|
||||||
|
}, [newUserKey]);
|
||||||
|
|
||||||
async function goToNotifications(e: any) {
|
async function goToNotifications(e: any) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
// request permissions to send notifications
|
// request permissions to send notifications
|
||||||
@ -122,7 +142,7 @@ export default function Layout() {
|
|||||||
|
|
||||||
function accountHeader() {
|
function accountHeader() {
|
||||||
const unreadNotifications = notifications?.filter(a => (a.created_at * 1000) > readNotifications).length;
|
const unreadNotifications = notifications?.filter(a => (a.created_at * 1000) > readNotifications).length;
|
||||||
const unreadDms = key ? totalUnread(filteredDms, key) : 0;
|
const unreadDms = publicKey ? totalUnread(filteredDms, publicKey) : 0;
|
||||||
return (
|
return (
|
||||||
<div className="header-actions">
|
<div className="header-actions">
|
||||||
<div className="btn btn-rnd" onClick={(e) => navigate("/search")}>
|
<div className="btn btn-rnd" onClick={(e) => navigate("/search")}>
|
||||||
@ -136,12 +156,12 @@ export default function Layout() {
|
|||||||
<Bell />
|
<Bell />
|
||||||
{unreadNotifications > 0 && (<span className="has-unread"></span>)}
|
{unreadNotifications > 0 && (<span className="has-unread"></span>)}
|
||||||
</div>
|
</div>
|
||||||
<ProfileImage pubkey={key || ""} showUsername={false} />
|
<ProfileImage pubkey={publicKey || ""} showUsername={false} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof isInit !== "boolean") {
|
if (typeof loggedOut !== "boolean") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -149,7 +169,7 @@ export default function Layout() {
|
|||||||
<header>
|
<header>
|
||||||
<div className="logo" onClick={() => navigate("/")}>Snort</div>
|
<div className="logo" onClick={() => navigate("/")}>Snort</div>
|
||||||
<div>
|
<div>
|
||||||
{key ? accountHeader() :
|
{publicKey ? accountHeader() :
|
||||||
<button type="button" onClick={() => navigate("/login")}>Login</button>
|
<button type="button" onClick={() => navigate("/login")}>Login</button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import * as secp from '@noble/secp256k1';
|
import * as secp from '@noble/secp256k1';
|
||||||
|
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import { setPrivateKey, setPublicKey, setRelays } from "State/Login";
|
import { setPrivateKey, setPublicKey, setRelays, setGeneratedPrivateKey } from "State/Login";
|
||||||
import { DefaultRelays, EmailRegex } from "Const";
|
import { DefaultRelays, EmailRegex } from "Const";
|
||||||
import { bech32ToHex } from "Util";
|
import { bech32ToHex } from "Util";
|
||||||
import { HexKey } from "Nostr";
|
import { HexKey } from "Nostr";
|
||||||
@ -66,23 +66,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
async function makeRandomKey() {
|
async function makeRandomKey() {
|
||||||
let newKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
|
let newKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
|
||||||
dispatch(setPrivateKey(newKey));
|
dispatch(setGeneratedPrivateKey(newKey));
|
||||||
|
|
||||||
try {
|
|
||||||
let rsp = await fetch("https://api.nostr.watch/v1/online");
|
|
||||||
if (rsp.ok) {
|
|
||||||
let online: string[] = await rsp.json();
|
|
||||||
let pickRandom = online.sort((a, b) => Math.random() >= 0.5 ? 1 : -1).slice(0, 4); // pick 4 random relays
|
|
||||||
|
|
||||||
let relayObjects = pickRandom.map(a => [a, { read: true, write: true }]);
|
|
||||||
dispatch(setRelays({
|
|
||||||
relays: Object.fromEntries(relayObjects),
|
|
||||||
createdAt: 1
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
navigate("/new");
|
navigate("/new");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,11 @@ export interface LoginStore {
|
|||||||
*/
|
*/
|
||||||
publicKey?: HexKey,
|
publicKey?: HexKey,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If user generated key on snort
|
||||||
|
*/
|
||||||
|
newUserKey: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the logged in users relays
|
* All the logged in users relays
|
||||||
*/
|
*/
|
||||||
@ -157,6 +162,7 @@ export const InitState = {
|
|||||||
loggedOut: undefined,
|
loggedOut: undefined,
|
||||||
publicKey: undefined,
|
publicKey: undefined,
|
||||||
privateKey: undefined,
|
privateKey: undefined,
|
||||||
|
newUserKey: false,
|
||||||
relays: {},
|
relays: {},
|
||||||
latestRelays: 0,
|
latestRelays: 0,
|
||||||
follows: [],
|
follows: [],
|
||||||
@ -242,6 +248,13 @@ const LoginSlice = createSlice({
|
|||||||
window.localStorage.setItem(PrivateKeyItem, action.payload);
|
window.localStorage.setItem(PrivateKeyItem, action.payload);
|
||||||
state.publicKey = secp.utils.bytesToHex(secp.schnorr.getPublicKey(action.payload));
|
state.publicKey = secp.utils.bytesToHex(secp.schnorr.getPublicKey(action.payload));
|
||||||
},
|
},
|
||||||
|
setGeneratedPrivateKey: (state, action: PayloadAction<HexKey>) => {
|
||||||
|
state.loggedOut = false;
|
||||||
|
state.newUserKey = true;
|
||||||
|
state.privateKey = action.payload;
|
||||||
|
window.localStorage.setItem(PrivateKeyItem, action.payload);
|
||||||
|
state.publicKey = secp.utils.bytesToHex(secp.schnorr.getPublicKey(action.payload));
|
||||||
|
},
|
||||||
setPublicKey: (state, action: PayloadAction<HexKey>) => {
|
setPublicKey: (state, action: PayloadAction<HexKey>) => {
|
||||||
window.localStorage.setItem(PublicKeyItem, action.payload);
|
window.localStorage.setItem(PublicKeyItem, action.payload);
|
||||||
state.loggedOut = false;
|
state.loggedOut = false;
|
||||||
@ -362,6 +375,7 @@ const LoginSlice = createSlice({
|
|||||||
export const {
|
export const {
|
||||||
init,
|
init,
|
||||||
setPrivateKey,
|
setPrivateKey,
|
||||||
|
setGeneratedPrivateKey,
|
||||||
setPublicKey,
|
setPublicKey,
|
||||||
setRelays,
|
setRelays,
|
||||||
removeRelay,
|
removeRelay,
|
||||||
|
Loading…
Reference in New Issue
Block a user