@@ -141,6 +151,7 @@ export const SearchPage = () => {
filterOptions={filterOptions}
muteLists={muteLists}
nsfwList={nsfwList}
+ el={scrollTargetRef.current}
/>
)}
{searchKind === SearchKindEnum.Users && (
@@ -263,13 +274,15 @@ type ModsResultProps = {
user: MuteLists
}
nsfwList: string[]
+ el: HTMLElement | null
}
const ModsResult = ({
filterOptions,
searchTerm,
muteLists,
- nsfwList
+ nsfwList,
+ el
}: ModsResultProps) => {
const { ndk } = useNDKContext()
const [mods, setMods] = useState([])
@@ -305,7 +318,9 @@ const ModsResult = ({
}, [ndk])
useEffect(() => {
+ scrollIntoView(el)
setPage(1)
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchTerm])
const filteredMods = useMemo(() => {
@@ -334,10 +349,12 @@ const ModsResult = ({
)
const handleNext = () => {
+ scrollIntoView(el)
setPage((prev) => prev + 1)
}
const handlePrev = () => {
+ scrollIntoView(el)
setPage((prev) => prev - 1)
}
@@ -392,7 +409,7 @@ const UsersResult = ({
}
setIsFetching(true)
- fetchEvents(filter, ['wss://purplepag.es', 'wss://user.kindpag.es'])
+ fetchEvents(filter)
.then((events) => {
const results = events.map((event) => {
const ndkEvent = new NDKEvent(undefined, event)
diff --git a/src/pages/settings/index.tsx b/src/pages/settings/index.tsx
index 60aa2c8..4c0f618 100644
--- a/src/pages/settings/index.tsx
+++ b/src/pages/settings/index.tsx
@@ -1,5 +1,4 @@
import { AdminSVG, PreferenceSVG, ProfileSVG, RelaySVG } from 'components/SVGs'
-import { MetadataController } from 'controllers'
import { useAppSelector } from 'hooks'
import { logout } from 'nostr-login'
import { useEffect, useState } from 'react'
@@ -57,15 +56,12 @@ const SettingTabs = () => {
const userState = useAppSelector((state) => state.user)
useEffect(() => {
- MetadataController.getInstance().then((controller) => {
- if (userState.auth && userState.user?.npub) {
- setIsAdmin(
- controller.adminNpubs.includes(userState.user.npub as string)
- )
- } else {
- setIsAdmin(false)
- }
- })
+ const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
+ if (userState.auth && userState.user?.npub) {
+ setIsAdmin(adminNpubs.includes(userState.user.npub as string))
+ } else {
+ setIsAdmin(false)
+ }
}, [userState])
const handleSignOut = () => {
diff --git a/src/pages/settings/profile.tsx b/src/pages/settings/profile.tsx
index 52f69f7..907d0f0 100644
--- a/src/pages/settings/profile.tsx
+++ b/src/pages/settings/profile.tsx
@@ -1,6 +1,6 @@
import { InputField } from 'components/Inputs'
import { ProfileQRButtonWithPopUp } from 'components/ProfileSection'
-import { useAppDispatch, useAppSelector } from 'hooks'
+import { useAppDispatch, useAppSelector, useNDKContext } from 'hooks'
import { kinds, nip19, UnsignedEvent, Event } from 'nostr-tools'
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
@@ -14,7 +14,6 @@ import {
profileFromEvent,
serializeProfile
} from '@nostr-dev-kit/ndk'
-import { RelayController } from 'controllers'
import { LoadingSpinner } from 'components/LoadingSpinner'
import { setUser } from 'store/reducers/user'
import placeholderMod from '../../assets/img/DEGMods Placeholder Img.png'
@@ -43,6 +42,7 @@ const defaultFormState: FormState = {
export const ProfileSettings = () => {
const dispatch = useAppDispatch()
const userState = useAppSelector((state) => state.user)
+ const { ndk, publish } = useNDKContext()
const [isPublishing, setIsPublishing] = useState(false)
const [formState, setFormState] = useState(defaultFormState)
@@ -163,9 +163,8 @@ export const ProfileSettings = () => {
return
}
- const publishedOnRelays = await RelayController.getInstance().publish(
- signedEvent as Event
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing failed or succeeded
if (publishedOnRelays.length === 0) {
diff --git a/src/pages/settings/relay.tsx b/src/pages/settings/relay.tsx
index ee79d94..1a32d28 100644
--- a/src/pages/settings/relay.tsx
+++ b/src/pages/settings/relay.tsx
@@ -1,21 +1,23 @@
-import { NDKRelayList } from '@nostr-dev-kit/ndk'
+import {
+ getRelayListForUser,
+ NDKEvent,
+ NDKRelayList,
+ NDKRelayStatus
+} from '@nostr-dev-kit/ndk'
import { InputField } from 'components/Inputs'
import { LoadingSpinner } from 'components/LoadingSpinner'
-import {
- MetadataController,
- RelayController,
- UserRelaysType
-} from 'controllers'
-import { useAppSelector, useDidMount } from 'hooks'
+import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
import { useEffect, useState } from 'react'
import { toast } from 'react-toastify'
+import { UserRelaysType } from 'types'
import { log, LogType, normalizeWebSocketURL, now } from 'utils'
const READ_MARKER = 'read'
const WRITE_MARKER = 'write'
export const RelaySettings = () => {
+ const { ndk, publish } = useNDKContext()
const userState = useAppSelector((state) => state.user)
const [ndkRelayList, setNDKRelayList] = useState(null)
const [isPublishing, setIsPublishing] = useState(false)
@@ -23,10 +25,8 @@ export const RelaySettings = () => {
const [inputValue, setInputValue] = useState('')
useEffect(() => {
- const fetchRelayList = async (pubkey: string) => {
- const metadataController = await MetadataController.getInstance()
- metadataController
- .getNDKRelayList(pubkey)
+ if (userState.auth && userState.user?.pubkey) {
+ getRelayListForUser(userState.user.pubkey as string, ndk)
.then((res) => {
setNDKRelayList(res)
})
@@ -38,14 +38,10 @@ export const RelaySettings = () => {
)
setNDKRelayList(null)
})
- }
-
- if (userState.auth && userState.user?.pubkey) {
- fetchRelayList(userState.user.pubkey as string)
} else {
setNDKRelayList(null)
}
- }, [userState])
+ }, [userState, ndk])
const handleAdd = async (relayUrl: string) => {
if (!ndkRelayList) return
@@ -78,11 +74,8 @@ export const RelaySettings = () => {
return
}
- const publishedOnRelays =
- await RelayController.getInstance().publishOnRelays(
- signedEvent,
- ndkRelayList.writeRelayUrls
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing failed or succeeded
if (publishedOnRelays.length === 0) {
@@ -140,11 +133,8 @@ export const RelaySettings = () => {
return
}
- const publishedOnRelays =
- await RelayController.getInstance().publishOnRelays(
- signedEvent,
- ndkRelayList.writeRelayUrls
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing failed or succeeded
if (publishedOnRelays.length === 0) {
@@ -214,11 +204,8 @@ export const RelaySettings = () => {
return
}
- const publishedOnRelays =
- await RelayController.getInstance().publishOnRelays(
- signedEvent,
- ndkRelayList.writeRelayUrls
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing failed or succeeded
if (publishedOnRelays.length === 0) {
@@ -382,17 +369,29 @@ const RelayListItem = ({
changeRelayType
}: RelayItemProps) => {
const [isConnected, setIsConnected] = useState(false)
+ const { ndk } = useNDKContext()
useDidMount(() => {
- RelayController.getInstance()
- .connectRelay(relayUrl)
- .then((relay) => {
- if (relay && relay.connected) {
- setIsConnected(true)
- } else {
- setIsConnected(false)
- }
- })
+ const ndkPool = ndk.pool
+
+ ndkPool.on('relay:connect', (relay) => {
+ if (relay.url === relayUrl) {
+ setIsConnected(true)
+ }
+ })
+
+ ndkPool.on('relay:disconnect', (relay) => {
+ if (relay.url === relayUrl) {
+ setIsConnected(false)
+ }
+ })
+
+ const relay = ndkPool.relays.get(relayUrl)
+ if (relay && relay.status >= NDKRelayStatus.CONNECTED) {
+ setIsConnected(true)
+ } else {
+ setIsConnected(false)
+ }
})
return (
diff --git a/src/pages/submitMod.tsx b/src/pages/submitMod.tsx
index 226b896..ba79874 100644
--- a/src/pages/submitMod.tsx
+++ b/src/pages/submitMod.tsx
@@ -29,7 +29,7 @@ export const SubmitModPage = () => {
useDidMount(async () => {
if (naddr) {
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
- const { identifier, kind, pubkey, relays = [] } = decoded.data
+ const { identifier, kind, pubkey } = decoded.data
const filter: NDKFilter = {
'#a': [identifier],
@@ -39,7 +39,7 @@ export const SubmitModPage = () => {
setIsFetching(true)
- fetchEvent(filter, relays)
+ fetchEvent(filter)
.then((event) => {
if (event) {
const extracted = extractModData(event)
diff --git a/src/styles/cardMod.css b/src/styles/cardMod.css
index 3028908..3250d41 100644
--- a/src/styles/cardMod.css
+++ b/src/styles/cardMod.css
@@ -96,6 +96,7 @@
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 2;
+ line-clamp: 2;
font-size: 20px;
line-height: 1.25;
color: rgba(255, 255, 255, 0.75);
@@ -107,6 +108,7 @@
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 2;
+ line-clamp: 2;
color: rgba(255, 255, 255, 0.5);
font-size: 15px;
line-height: 1.5;
@@ -119,11 +121,12 @@
justify-content: start;
align-items: center;
font-size: 14px;
- background: rgba(255,255,255,0.05);
+ background: rgba(255, 255, 255, 0.05);
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
-webkit-line-clamp: 1;
+ line-clamp: 1;
}
.cMMFootReactions {
@@ -143,3 +146,12 @@
align-items: center;
color: rgba(255, 255, 255, 0.25);
}
+
+.IBMSMSMBSSTagsTag.IBMSMSMBSSTagsTagNSFW.IBMSMSMBSSTagsTagNSFWCard {
+ position: absolute;
+ bottom: 10px;
+ right: 10px;
+ -webkit-backdrop-filter: blur(10px);
+ backdrop-filter: blur(10px);
+ background: rgba(35, 35, 35, 0.85);
+}
diff --git a/src/types/user.ts b/src/types/user.ts
index 551bd1f..059ba84 100644
--- a/src/types/user.ts
+++ b/src/types/user.ts
@@ -1,3 +1,9 @@
import { NDKUserProfile } from '@nostr-dev-kit/ndk'
export type UserProfile = NDKUserProfile | null
+
+export enum UserRelaysType {
+ Read = 'readRelayUrls',
+ Write = 'writeRelayUrls',
+ Both = 'bothRelayUrls'
+}
diff --git a/src/utils/nostr.ts b/src/utils/nostr.ts
index f3711b0..130d023 100644
--- a/src/utils/nostr.ts
+++ b/src/utils/nostr.ts
@@ -9,9 +9,8 @@ import {
UnsignedEvent
} from 'nostr-tools'
import { toast } from 'react-toastify'
-import { RelayController } from '../controllers'
import { log, LogType } from './utils'
-import { NDKEvent } from '@nostr-dev-kit/ndk'
+import NDK, { NDKEvent } from '@nostr-dev-kit/ndk'
/**
* Get the current time in seconds since the Unix epoch (January 1, 1970).
@@ -123,7 +122,11 @@ export const extractZapAmount = (event: Event): number => {
* @param unsignedEvent - The event object which needs to be signed before publishing.
* @returns - A promise that resolves to boolean indicating whether the event was successfully signed and published
*/
-export const signAndPublish = async (unsignedEvent: UnsignedEvent) => {
+export const signAndPublish = async (
+ unsignedEvent: UnsignedEvent,
+ ndk: NDK,
+ publish: (event: NDKEvent) => Promise
+) => {
// Sign the event. This returns a signed event or null if signing fails.
const signedEvent = await window.nostr
?.signEvent(unsignedEvent)
@@ -138,11 +141,10 @@ export const signAndPublish = async (unsignedEvent: UnsignedEvent) => {
// If the event couldn't be signed, exit the function and return null.
if (!signedEvent) return false
- // Publish the signed event to the relays using the RelayController.
+ // Publish the signed event to the relays.
// This returns an array of relay URLs where the event was successfully published.
- const publishedOnRelays = await RelayController.getInstance().publish(
- signedEvent as Event
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing to the relays failed
if (publishedOnRelays.length === 0) {
@@ -170,7 +172,9 @@ export const signAndPublish = async (unsignedEvent: UnsignedEvent) => {
*/
export const sendDMUsingRandomKey = async (
message: string,
- receiver: string
+ receiver: string,
+ ndk: NDK,
+ publish: (event: NDKEvent) => Promise
) => {
// Generate a random secret key for encrypting the message
const secretKey = generateSecretKey()
@@ -201,11 +205,8 @@ export const sendDMUsingRandomKey = async (
// Finalize and sign the event using the generated secret key
const signedEvent = finalizeEvent(unsignedEvent, secretKey)
- // Publish the signed event (the encrypted DM) to the relays
- const publishedOnRelays = await RelayController.getInstance().publishDM(
- signedEvent,
- receiver
- )
+ const ndkEvent = new NDKEvent(ndk, signedEvent)
+ const publishedOnRelays = await publish(ndkEvent)
// Handle cases where publishing to the relays failed
if (publishedOnRelays.length === 0) {
diff --git a/src/utils/utils.ts b/src/utils/utils.ts
index b321c91..6c904e0 100644
--- a/src/utils/utils.ts
+++ b/src/utils/utils.ts
@@ -135,3 +135,14 @@ export const handleModImageError = (
) => {
e.currentTarget.src = import.meta.env.VITE_FALLBACK_MOD_IMAGE
}
+
+export const scrollIntoView = (el: HTMLElement | null) => {
+ if (el) {
+ setTimeout(() => {
+ el.scrollIntoView({
+ behavior: 'smooth',
+ block: 'start'
+ })
+ }, 100)
+ }
+}