diff --git a/packages/app/src/Const.ts b/packages/app/src/Const.ts index d7e0a6e..dd00120 100644 --- a/packages/app/src/Const.ts +++ b/packages/app/src/Const.ts @@ -41,7 +41,7 @@ export const ProfileCacheExpire = 1_000 * 60 * 30; export const DefaultRelays = new Map([ ["wss://relay.snort.social", { read: true, write: true }], ["wss://nostr.wine", { read: true, write: false }], - ["wss://nos.lol", { read: true, write: false }], + ["wss://nos.lol", { read: true, write: true }], ]); /** diff --git a/packages/app/src/Pages/Layout.tsx b/packages/app/src/Pages/Layout.tsx index dfdf3a0..28810a9 100644 --- a/packages/app/src/Pages/Layout.tsx +++ b/packages/app/src/Pages/Layout.tsx @@ -7,7 +7,7 @@ import { FormattedMessage } from "react-intl"; import { RelaySettings } from "@snort/nostr"; import messages from "./messages"; -import { bech32ToHex, randomSample } from "Util"; +import { bech32ToHex, randomSample, unixNowMs, unwrap } from "Util"; import Icon from "Icons/Icon"; import { RootState } from "State/Store"; import { init, setRelays } from "State/Login"; @@ -19,7 +19,7 @@ import useModeration from "Hooks/useModeration"; import { NoteCreator } from "Element/NoteCreator"; import { db } from "Db"; import useEventPublisher from "Feed/EventPublisher"; -import { SnortPubKey } from "Const"; +import { DefaultRelays, SnortPubKey } from "Const"; import SubDebug from "Element/SubDebug"; import { preload } from "Cache"; import { useDmCache } from "Hooks/useDmsCache"; @@ -129,11 +129,14 @@ export default function Layout() { const online: string[] = await rsp.json(); const pickRandom = randomSample(online, 4); const relayObjects = pickRandom.map(a => [a, { read: true, write: true }]); - newRelays = Object.fromEntries(relayObjects); + newRelays = { + ...Object.fromEntries(relayObjects), + ...Object.fromEntries(DefaultRelays.entries()), + }; dispatch( setRelays({ relays: newRelays, - createdAt: 1, + createdAt: unixNowMs(), }) ); } @@ -141,7 +144,7 @@ export default function Layout() { console.warn(e); } - const ev = await pub.addFollow(bech32ToHex(SnortPubKey), newRelays); + const ev = await pub.addFollow([bech32ToHex(SnortPubKey), unwrap(publicKey)], newRelays); pub.broadcast(ev); } diff --git a/packages/app/src/Pages/Login.tsx b/packages/app/src/Pages/Login.tsx index 05b6b39..dffc7d7 100644 --- a/packages/app/src/Pages/Login.tsx +++ b/packages/app/src/Pages/Login.tsx @@ -72,7 +72,7 @@ export default function LoginPage() { const { formatMessage } = useIntl(); const { proxy } = useImgProxy(); const hasNip7 = "nostr" in window; - const isSecure = window.location.protocol === "https:"; + const hasSubtleCrypto = window.crypto.subtle !== undefined; useEffect(() => { if (publicKey) { @@ -92,7 +92,7 @@ export default function LoginPage() { }); try { if (key.startsWith("nsec")) { - if (!isSecure) { + if (!hasSubtleCrypto) { throw new Error(insecureMsg); } const hexKey = bech32ToHex(key); @@ -108,14 +108,14 @@ export default function LoginPage() { const hexKey = await getNip05PubKey(key); dispatch(setPublicKey(hexKey)); } else if (key.match(MnemonicRegex)) { - if (!isSecure) { + if (!hasSubtleCrypto) { throw new Error(insecureMsg); } const ent = generateBip39Entropy(key); const keyHex = entropyToDerivedKey(ent); dispatch(setPrivateKey(keyHex)); } else if (secp.utils.isValidPrivateKey(key)) { - if (!isSecure) { + if (!hasSubtleCrypto) { throw new Error(insecureMsg); } dispatch(setPrivateKey(key)); @@ -178,7 +178,7 @@ export default function LoginPage() { } function generateKey() { - if (!isSecure) return; + if (!hasSubtleCrypto) return; return ( <> @@ -205,7 +205,7 @@ export default function LoginPage() { } function installExtension() { - if (isSecure) return; + if (hasSubtleCrypto) return; return ( <> diff --git a/packages/app/src/Pages/settings/Profile.tsx b/packages/app/src/Pages/settings/Profile.tsx index 1856746..a48ed0b 100644 --- a/packages/app/src/Pages/settings/Profile.tsx +++ b/packages/app/src/Pages/settings/Profile.tsx @@ -6,17 +6,18 @@ import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faShop } from "@fortawesome/free-solid-svg-icons"; +import { HexKey, TaggedRawEvent } from "@snort/nostr"; import useEventPublisher from "Feed/EventPublisher"; import { useUserProfile } from "Hooks/useUserProfile"; import { hexToBech32, openFile } from "Util"; import Copy from "Element/Copy"; import { RootState } from "State/Store"; -import { HexKey } from "@snort/nostr"; import useFileUpload from "Upload"; import messages from "./messages"; -import AsyncButton from "../../Element/AsyncButton"; +import AsyncButton from "Element/AsyncButton"; +import { mapEventToProfile, UserCache } from "Cache"; export interface ProfileSettingsProps { avatar?: boolean; @@ -80,6 +81,11 @@ export default function ProfileSettings(props: ProfileSettingsProps) { const ev = await publisher.metadata(userCopy); console.debug(ev); publisher.broadcast(ev); + + const newProfile = mapEventToProfile(ev as TaggedRawEvent); + if (newProfile) { + await UserCache.set(newProfile); + } } async function uploadFile() { diff --git a/packages/app/src/State/Cache.ts b/packages/app/src/State/Cache.ts deleted file mode 100644 index bdb4206..0000000 --- a/packages/app/src/State/Cache.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { TaggedRawEvent } from "@snort/nostr"; - -export interface TimelineCache { - key: string; - main: TaggedRawEvent[]; - related: TaggedRawEvent[]; - latest: TaggedRawEvent[]; - parent: TaggedRawEvent[]; -} - -export interface FeedCache { - timeline: TimelineCache; -} - -const InitState = { - timeline: { - key: "", - main: [], - related: [], - latest: [], - parent: [], - }, -} as FeedCache; - -const CacheSlice = createSlice({ - name: "Cache", - initialState: InitState, - reducers: { - setTimeline: (state, action: PayloadAction) => { - state.timeline = action.payload; - }, - }, -}); - -export const { setTimeline } = CacheSlice.actions; - -export const reducer = CacheSlice.reducer; diff --git a/packages/app/src/State/Login.ts b/packages/app/src/State/Login.ts index 4157733..cb25046 100644 --- a/packages/app/src/State/Login.ts +++ b/packages/app/src/State/Login.ts @@ -6,7 +6,7 @@ import { DefaultRelays } from "Const"; import { RelaySettings } from "@snort/nostr"; import type { AppDispatch, RootState } from "State/Store"; import { ImgProxySettings } from "Hooks/useImgProxy"; -import { sanitizeRelayUrl } from "Util"; +import { sanitizeRelayUrl, unwrap } from "Util"; import { DmCache } from "Cache"; const PrivateKeyItem = "secret"; @@ -300,7 +300,9 @@ const LoginSlice = createSlice({ if (lastRelayList) { state.relays = JSON.parse(lastRelayList); } else { - state.relays = Object.fromEntries(DefaultRelays.entries()); + state.relays = Object.fromEntries( + [...DefaultRelays.entries()].map(a => [unwrap(sanitizeRelayUrl(a[0])), a[1]]) + ); } const lastFollows = window.localStorage.getItem(FollowList); diff --git a/packages/app/src/State/Store.ts b/packages/app/src/State/Store.ts index 6d8e7bd..2066283 100644 --- a/packages/app/src/State/Store.ts +++ b/packages/app/src/State/Store.ts @@ -1,11 +1,9 @@ import { configureStore } from "@reduxjs/toolkit"; import { reducer as LoginReducer } from "State/Login"; -import { reducer as CacheReducer } from "State/Cache"; const store = configureStore({ reducer: { login: LoginReducer, - cache: CacheReducer, }, });