try again button, user blog tab load, no game text #181
@ -1,11 +1,12 @@
|
|||||||
import { RouterProvider } from 'react-router-dom'
|
import { RouterProvider } from 'react-router-dom'
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useMemo } from 'react'
|
||||||
import { routerWithNdkContext } from 'routes'
|
import { routerWithNdkContext as routerWithState } from 'routes'
|
||||||
import { useNDKContext } from 'hooks'
|
import { useNDKContext } from 'hooks'
|
||||||
import './styles/styles.css'
|
import './styles/styles.css'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const ndkContext = useNDKContext()
|
const ndkContext = useNDKContext()
|
||||||
|
const router = useMemo(() => routerWithState(ndkContext), [ndkContext])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Find the element with id 'root'
|
// Find the element with id 'root'
|
||||||
@ -24,7 +25,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <RouterProvider router={routerWithNdkContext(ndkContext)} />
|
return <RouterProvider router={router} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
@ -252,7 +252,7 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
log(
|
log(
|
||||||
true,
|
false, // Too many failed requests, turned off for clarity
|
||||||
LogType.Error,
|
LogType.Error,
|
||||||
`An error occurred in fetching user's (${hexKey}) ${userRelaysType}`,
|
`An error occurred in fetching user's (${hexKey}) ${userRelaysType}`,
|
||||||
err
|
err
|
||||||
|
@ -39,7 +39,7 @@ export const useComments = (
|
|||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
log(
|
log(
|
||||||
true,
|
false, // Too many failed requests, turned off for clarity
|
||||||
LogType.Error,
|
LogType.Error,
|
||||||
`An error occurred in fetching user's (${author}) ${UserRelaysType.Read}`,
|
`An error occurred in fetching user's (${author}) ${UserRelaysType.Read}`,
|
||||||
err
|
err
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { Link } from 'react-router-dom'
|
||||||
import styles from '../styles/footer.module.scss'
|
import styles from '../styles/footer.module.scss'
|
||||||
|
import { appRoutes, getProfilePageRoute } from 'routes'
|
||||||
|
|
||||||
export const Footer = () => {
|
export const Footer = () => {
|
||||||
return (
|
return (
|
||||||
@ -7,6 +9,7 @@ export const Footer = () => {
|
|||||||
<p className={styles.secMainFooterPara}>
|
<p className={styles.secMainFooterPara}>
|
||||||
Built with
|
Built with
|
||||||
<a
|
<a
|
||||||
|
rel='noopener'
|
||||||
className={styles.secMainFooterParaLink}
|
className={styles.secMainFooterParaLink}
|
||||||
href='https://github.com/nostr-protocol/nostr'
|
href='https://github.com/nostr-protocol/nostr'
|
||||||
target='_blank'
|
target='_blank'
|
||||||
@ -14,21 +17,26 @@ export const Footer = () => {
|
|||||||
Nostr
|
Nostr
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
by
|
by
|
||||||
<a
|
<Link
|
||||||
className={styles.secMainFooterParaLink}
|
className={styles.secMainFooterParaLink}
|
||||||
href='https://degmods.com/profile/nprofile1qqsre6jgq6c7r2vzn5cdtju20qq36sn3cer5avc4x8kfru5pzrlr7sqnancjp'
|
to={getProfilePageRoute(
|
||||||
|
'nprofile1qqsre6jgq6c7r2vzn5cdtju20qq36sn3cer5avc4x8kfru5pzrlr7sqnancjp'
|
||||||
|
)}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
>
|
>
|
||||||
Freakoverse
|
Freakoverse
|
||||||
</a>
|
</Link>
|
||||||
, with the support of{' '}
|
, with the support of{' '}
|
||||||
<a className={styles.secMainFooterParaLink} href='backers.html'>
|
<Link
|
||||||
|
className={styles.secMainFooterParaLink}
|
||||||
|
to={appRoutes.supporters}
|
||||||
|
>
|
||||||
Supporters
|
Supporters
|
||||||
</a>
|
</Link>
|
||||||
. Check our
|
. Check our
|
||||||
<a className={styles.secMainFooterParaLink} href='backup.html'>
|
<Link className={styles.secMainFooterParaLink} to={appRoutes.backup}>
|
||||||
Backup Plan
|
Backup Plan
|
||||||
</a>
|
</Link>
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@ export const Layout = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [ndk, dispatch])
|
}, [dispatch, ndk])
|
||||||
|
|
||||||
// calculate user's wot
|
// calculate user's wot
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -60,7 +60,7 @@ export const Layout = () => {
|
|||||||
toast.error('An error occurred in calculating user web-of-trust!')
|
toast.error('An error occurred in calculating user web-of-trust!')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [ndk, userState.user, dispatch])
|
}, [dispatch, ndk, userState.user?.pubkey])
|
||||||
|
|
||||||
// get site's wot level
|
// get site's wot level
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -106,7 +106,7 @@ export const Layout = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [userState.user, dispatch, fetchEventFromUserRelays])
|
}, [dispatch, fetchEventFromUserRelays, userState.user?.pubkey])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
126
src/pages/backup.tsx
Normal file
126
src/pages/backup.tsx
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { capitalizeEachWord } from 'utils'
|
||||||
|
import '../styles/backup.css'
|
||||||
|
import backupPlanImg from '../assets/img/DEG Mods Backup Plan.png'
|
||||||
|
// import placeholder from '../assets/img/DEGMods Placeholder Img.png'
|
||||||
|
interface BackupItemProps {
|
||||||
|
name: string
|
||||||
|
image: string
|
||||||
|
link: string
|
||||||
|
type: 'repo' | 'alt' | 'exe'
|
||||||
|
}
|
||||||
|
const BACKUP_LIST: BackupItemProps[] = [
|
||||||
|
// {
|
||||||
|
// name: 'Github',
|
||||||
|
// type: 'repo',
|
||||||
|
// image:
|
||||||
|
// 'https://www.c-sharpcorner.com/article/create-github-repository-and-add-newexisting-project-using-github-desktop/Images/github.png',
|
||||||
|
// link: '#'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Github, but nostr',
|
||||||
|
// type: 'repo',
|
||||||
|
// image: 'https://vitorpamplona.com/images/nostr.gif',
|
||||||
|
// link: '#'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'name',
|
||||||
|
// type: 'alt',
|
||||||
|
// image: placeholder,
|
||||||
|
// link: '#'
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: '',
|
||||||
|
// type: 'exe',
|
||||||
|
// image: placeholder,
|
||||||
|
// link: '#'
|
||||||
|
// }
|
||||||
|
]
|
||||||
|
|
||||||
|
const BackupItem = ({ name, image, link, type }: BackupItemProps) => {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className='backupListLink'
|
||||||
|
href={link}
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(15deg, rgba(0,0,0,0.75), rgba(0,0,0,0.25)),
|
||||||
|
url("${image}") center / cover no-repeat,
|
||||||
|
linear-gradient(45deg, rgba(0,0,0,0.1), rgba(255,255,255,0.01) 50%, rgba(0,0,0,0.1))`
|
||||||
|
}}
|
||||||
|
target='_blank'
|
||||||
|
>
|
||||||
|
<div className='backupListLinkInside'>
|
||||||
|
<h3>
|
||||||
|
{type === 'exe' ? type.toUpperCase() : capitalizeEachWord(type)}:{' '}
|
||||||
|
{name}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BackupPage = () => {
|
||||||
|
return (
|
||||||
|
<div className='InnerBodyMain'>
|
||||||
|
<div className='ContainerMain'>
|
||||||
|
<div className='IBMSecMainGroup'>
|
||||||
|
<div className='IBMSecMain'>
|
||||||
|
<div className='AboutSec'>
|
||||||
|
<div className='LearnText'>
|
||||||
|
<div className='LearnTextInside'>
|
||||||
|
<h1
|
||||||
|
className='LearnTextHeading'
|
||||||
|
style={{ textAlign: 'center' }}
|
||||||
|
>
|
||||||
|
Backup Plan: Repos, Alts, EXE
|
||||||
|
</h1>
|
||||||
|
<img alt='' src={backupPlanImg} />
|
||||||
|
<p className='LearnTextPara'>
|
||||||
|
It's pretty clear that authoritarianism and censorship is on
|
||||||
|
the rise, on all fronts, and from what can be seen, any idea
|
||||||
|
that push for the opposite gets attacked. That's why DEG
|
||||||
|
Mods is running on Nostr, and that's why we're also writing
|
||||||
|
this backup plan.
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
<h3 className='LearnTextHeading'>Repositories</h3>
|
||||||
|
<p className='LearnTextPara'>
|
||||||
|
Wherever we can, we'll put DEG Mods' code on multiple
|
||||||
|
repositories such as Github, and (github but on nostr).
|
||||||
|
Below you can find the links where we've uploaded the site's
|
||||||
|
code to.
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
<h3 className='LearnTextHeading'>Alternatives</h3>
|
||||||
|
<p className='LearnTextPara'>
|
||||||
|
With the repositories for DEG Mods is up on multiple places,
|
||||||
|
we encourage people to take the code and duplicate it
|
||||||
|
elsewhere. Fork it, change the design, remove or add systems
|
||||||
|
and features, and make your own version. Below you can find
|
||||||
|
links of alts that we've found.
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
<h3 className='LearnTextHeading'>EXE</h3>
|
||||||
|
<p className='LearnTextPara'>
|
||||||
|
One last push we'd like to do is to create a .exe that'll
|
||||||
|
open up DEG Mods on your PC, as if you've opened the website
|
||||||
|
normally, with almost all of the functionalities you'd
|
||||||
|
expect (if not all). We want to do this so that in case
|
||||||
|
there are no alternatives, or that they're getting shut
|
||||||
|
down, then you can just rely on this instead. The link to it
|
||||||
|
will be added here the moment it becomes available.
|
||||||
|
<br />
|
||||||
|
</p>
|
||||||
|
<div className='backupList'>
|
||||||
|
{BACKUP_LIST.map((b) => (
|
||||||
|
<BackupItem {...b} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -13,6 +13,7 @@ import {
|
|||||||
} from 'types'
|
} from 'types'
|
||||||
import {
|
import {
|
||||||
DEFAULT_FILTER_OPTIONS,
|
DEFAULT_FILTER_OPTIONS,
|
||||||
|
getFallbackPubkey,
|
||||||
getLocalStorageItem,
|
getLocalStorageItem,
|
||||||
log,
|
log,
|
||||||
LogType
|
LogType
|
||||||
@ -41,7 +42,8 @@ export const blogRouteLoader =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userState = store.getState().user
|
const userState = store.getState().user
|
||||||
const loggedInUserPubkey = userState?.user?.pubkey as string | undefined
|
const loggedInUserPubkey =
|
||||||
|
(userState?.user?.pubkey as string | undefined) || getFallbackPubkey()
|
||||||
|
|
||||||
// Check if editing and the user is the original author
|
// Check if editing and the user is the original author
|
||||||
// Redirect if NOT
|
// Redirect if NOT
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
DEFAULT_FILTER_OPTIONS,
|
DEFAULT_FILTER_OPTIONS,
|
||||||
extractBlogCardDetails,
|
extractBlogCardDetails,
|
||||||
extractModData,
|
extractModData,
|
||||||
|
getFallbackPubkey,
|
||||||
getLocalStorageItem,
|
getLocalStorageItem,
|
||||||
getReportingSet,
|
getReportingSet,
|
||||||
log,
|
log,
|
||||||
@ -46,7 +47,8 @@ export const modRouteLoader =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userState = store.getState().user
|
const userState = store.getState().user
|
||||||
const loggedInUserPubkey = userState?.user?.pubkey as string | undefined
|
const loggedInUserPubkey =
|
||||||
|
(userState?.user?.pubkey as string | undefined) || getFallbackPubkey()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Set up the filters
|
// Set up the filters
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { NDKContextType } from 'contexts/NDKContext'
|
import { NDKContextType } from 'contexts/NDKContext'
|
||||||
import { store } from 'store'
|
import { store } from 'store'
|
||||||
import { MuteLists } from 'types'
|
import { MuteLists } from 'types'
|
||||||
import { getReportingSet, CurationSetIdentifiers, log, LogType } from 'utils'
|
import {
|
||||||
|
getReportingSet,
|
||||||
|
CurationSetIdentifiers,
|
||||||
|
log,
|
||||||
|
LogType,
|
||||||
|
getFallbackPubkey
|
||||||
|
} from 'utils'
|
||||||
|
|
||||||
export interface ModsPageLoaderResult {
|
export interface ModsPageLoaderResult {
|
||||||
muteLists: {
|
muteLists: {
|
||||||
@ -31,15 +37,11 @@ export const modsRouteLoader = (ndkContext: NDKContextType) => async () => {
|
|||||||
|
|
||||||
// Get the current state
|
// Get the current state
|
||||||
const userState = store.getState().user
|
const userState = store.getState().user
|
||||||
|
const loggedInUserPubkey =
|
||||||
// Check if current user is logged in
|
(userState?.user?.pubkey as string | undefined) || getFallbackPubkey()
|
||||||
let userPubkey: string | undefined
|
|
||||||
if (userState.auth && userState.user?.pubkey) {
|
|
||||||
userPubkey = userState.user.pubkey as string
|
|
||||||
}
|
|
||||||
|
|
||||||
const settled = await Promise.allSettled([
|
const settled = await Promise.allSettled([
|
||||||
ndkContext.getMuteLists(userPubkey),
|
ndkContext.getMuteLists(loggedInUserPubkey),
|
||||||
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
||||||
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
||||||
])
|
])
|
||||||
|
@ -46,7 +46,6 @@ export const ProfilePage = () => {
|
|||||||
profilePubkey,
|
profilePubkey,
|
||||||
profile,
|
profile,
|
||||||
isBlocked: _isBlocked,
|
isBlocked: _isBlocked,
|
||||||
isOwnProfile,
|
|
||||||
repostList,
|
repostList,
|
||||||
muteLists,
|
muteLists,
|
||||||
nsfwList
|
nsfwList
|
||||||
@ -60,6 +59,10 @@ export const ProfilePage = () => {
|
|||||||
const displayName =
|
const displayName =
|
||||||
profile?.displayName || profile?.name || '[name not set up]'
|
profile?.displayName || profile?.name || '[name not set up]'
|
||||||
const [showReportPopUp, setShowReportPopUp] = useState(false)
|
const [showReportPopUp, setShowReportPopUp] = useState(false)
|
||||||
|
const isOwnProfile =
|
||||||
|
userState.auth &&
|
||||||
|
userState.user?.pubkey &&
|
||||||
|
userState.user.pubkey === profilePubkey
|
||||||
|
|
||||||
const [isBlocked, setIsBlocked] = useState(_isBlocked)
|
const [isBlocked, setIsBlocked] = useState(_isBlocked)
|
||||||
const handleBlock = async () => {
|
const handleBlock = async () => {
|
||||||
@ -661,7 +664,7 @@ const ReportUserPopup = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ProfileTabBlogs = () => {
|
const ProfileTabBlogs = () => {
|
||||||
const { profile, muteLists, nsfwList } =
|
const { profilePubkey, muteLists, nsfwList } =
|
||||||
useLoaderData() as ProfilePageLoaderResult
|
useLoaderData() as ProfilePageLoaderResult
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const { fetchEvents } = useNDKContext()
|
const { fetchEvents } = useNDKContext()
|
||||||
@ -669,7 +672,7 @@ const ProfileTabBlogs = () => {
|
|||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const blogfilter: NDKFilter = useMemo(() => {
|
const blogfilter: NDKFilter = useMemo(() => {
|
||||||
const filter: NDKFilter = {
|
const filter: NDKFilter = {
|
||||||
authors: [profile?.pubkey as string],
|
authors: [profilePubkey],
|
||||||
kinds: [kinds.LongFormArticle]
|
kinds: [kinds.LongFormArticle]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,13 +686,13 @@ const ProfileTabBlogs = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filter
|
return filter
|
||||||
}, [filterOptions.nsfw, filterOptions.source, profile?.pubkey])
|
}, [filterOptions.nsfw, filterOptions.source, profilePubkey])
|
||||||
|
|
||||||
const [page, setPage] = useState(1)
|
const [page, setPage] = useState(1)
|
||||||
const [hasMore, setHasMore] = useState(false)
|
const [hasMore, setHasMore] = useState(false)
|
||||||
const [blogs, setBlogs] = useState<Partial<BlogCardDetails>[]>([])
|
const [blogs, setBlogs] = useState<Partial<BlogCardDetails>[]>([])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (profile) {
|
if (profilePubkey) {
|
||||||
// Initial blog fetch, go beyond limit to check for next
|
// Initial blog fetch, go beyond limit to check for next
|
||||||
const filter: NDKFilter = {
|
const filter: NDKFilter = {
|
||||||
...blogfilter,
|
...blogfilter,
|
||||||
@ -704,7 +707,7 @@ const ProfileTabBlogs = () => {
|
|||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [blogfilter, fetchEvents, profile])
|
}, [blogfilter, fetchEvents, profilePubkey])
|
||||||
|
|
||||||
const handleNext = useCallback(() => {
|
const handleNext = useCallback(() => {
|
||||||
if (isLoading) return
|
if (isLoading) return
|
||||||
@ -758,7 +761,7 @@ const ProfileTabBlogs = () => {
|
|||||||
let _blogs = blogs || []
|
let _blogs = blogs || []
|
||||||
const isAdmin = userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
|
const isAdmin = userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
|
||||||
const isOwner =
|
const isOwner =
|
||||||
userState.user?.pubkey && userState.user.pubkey === profile?.pubkey
|
userState.user?.pubkey && userState.user.pubkey === profilePubkey
|
||||||
const isUnmoderatedFully =
|
const isUnmoderatedFully =
|
||||||
filterOptions.moderated === ModeratedFilter.Unmoderated_Fully
|
filterOptions.moderated === ModeratedFilter.Unmoderated_Fully
|
||||||
|
|
||||||
@ -815,7 +818,7 @@ const ProfileTabBlogs = () => {
|
|||||||
muteLists.user.authors,
|
muteLists.user.authors,
|
||||||
muteLists.user.replaceableEvents,
|
muteLists.user.replaceableEvents,
|
||||||
nsfwList,
|
nsfwList,
|
||||||
profile?.pubkey,
|
profilePubkey,
|
||||||
userState.user?.npub,
|
userState.user?.npub,
|
||||||
userState.user?.pubkey
|
userState.user?.pubkey
|
||||||
])
|
])
|
||||||
@ -826,10 +829,7 @@ const ProfileTabBlogs = () => {
|
|||||||
<LoadingSpinner desc={'Loading...'} />
|
<LoadingSpinner desc={'Loading...'} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<BlogsFilter
|
<BlogsFilter filterKey={'filter-blog'} author={profilePubkey} />
|
||||||
filterKey={'filter-blog'}
|
|
||||||
author={profile?.pubkey as string}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className='IBMSMList IBMSMListAlt'>
|
<div className='IBMSMList IBMSMListAlt'>
|
||||||
{moderatedAndSortedBlogs.map((b) => (
|
{moderatedAndSortedBlogs.map((b) => (
|
||||||
|
@ -6,6 +6,7 @@ import { store } from 'store'
|
|||||||
import { MuteLists, UserProfile } from 'types'
|
import { MuteLists, UserProfile } from 'types'
|
||||||
import {
|
import {
|
||||||
CurationSetIdentifiers,
|
CurationSetIdentifiers,
|
||||||
|
getFallbackPubkey,
|
||||||
getReportingSet,
|
getReportingSet,
|
||||||
log,
|
log,
|
||||||
LogType,
|
LogType,
|
||||||
@ -16,7 +17,6 @@ export interface ProfilePageLoaderResult {
|
|||||||
profilePubkey: string
|
profilePubkey: string
|
||||||
profile: UserProfile
|
profile: UserProfile
|
||||||
isBlocked: boolean
|
isBlocked: boolean
|
||||||
isOwnProfile: boolean
|
|
||||||
muteLists: {
|
muteLists: {
|
||||||
admin: MuteLists
|
admin: MuteLists
|
||||||
user: MuteLists
|
user: MuteLists
|
||||||
@ -58,21 +58,17 @@ export const profileRouteLoader =
|
|||||||
|
|
||||||
// Get the current state
|
// Get the current state
|
||||||
const userState = store.getState().user
|
const userState = store.getState().user
|
||||||
|
const loggedInUserPubkey =
|
||||||
// Check if current user is logged in
|
(userState?.user?.pubkey as string | undefined) || getFallbackPubkey()
|
||||||
let userPubkey: string | undefined
|
|
||||||
if (userState.auth && userState.user?.pubkey) {
|
|
||||||
userPubkey = userState.user.pubkey as string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect if profile naddr is missing
|
// Redirect if profile naddr is missing
|
||||||
// - home if user is not logged
|
// - home if user is not logged
|
||||||
let profileRoute = appRoutes.home
|
let profileRoute = appRoutes.home
|
||||||
if (!profilePubkey && userPubkey) {
|
if (!profilePubkey && loggedInUserPubkey) {
|
||||||
// - own profile
|
// - own profile
|
||||||
profileRoute = getProfilePageRoute(
|
profileRoute = getProfilePageRoute(
|
||||||
nip19.nprofileEncode({
|
nip19.nprofileEncode({
|
||||||
pubkey: userPubkey
|
pubkey: loggedInUserPubkey
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -83,7 +79,6 @@ export const profileRouteLoader =
|
|||||||
profilePubkey: profilePubkey,
|
profilePubkey: profilePubkey,
|
||||||
profile: {},
|
profile: {},
|
||||||
isBlocked: false,
|
isBlocked: false,
|
||||||
isOwnProfile: false,
|
|
||||||
muteLists: {
|
muteLists: {
|
||||||
admin: {
|
admin: {
|
||||||
authors: [],
|
authors: [],
|
||||||
@ -98,14 +93,9 @@ export const profileRouteLoader =
|
|||||||
repostList: []
|
repostList: []
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user the user is logged in
|
|
||||||
if (userState.auth && userState.user?.pubkey) {
|
|
||||||
result.isOwnProfile = userState.user.pubkey === profilePubkey
|
|
||||||
}
|
|
||||||
|
|
||||||
const settled = await Promise.allSettled([
|
const settled = await Promise.allSettled([
|
||||||
ndkContext.findMetadata(profilePubkey),
|
ndkContext.findMetadata(profilePubkey),
|
||||||
ndkContext.getMuteLists(userPubkey),
|
ndkContext.getMuteLists(loggedInUserPubkey),
|
||||||
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
||||||
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
||||||
])
|
])
|
||||||
|
@ -39,6 +39,7 @@ import {
|
|||||||
scrollIntoView
|
scrollIntoView
|
||||||
} from 'utils'
|
} from 'utils'
|
||||||
import { useCuratedSet } from 'hooks/useCuratedSet'
|
import { useCuratedSet } from 'hooks/useCuratedSet'
|
||||||
|
import dedup from 'utils/nostr'
|
||||||
|
|
||||||
enum SearchKindEnum {
|
enum SearchKindEnum {
|
||||||
Mods = 'Mods',
|
Mods = 'Mods',
|
||||||
@ -508,6 +509,11 @@ const GamesResult = ({ searchTerm }: GamesResultProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{searchTerm !== '' && filteredGames.length === 0 && (
|
||||||
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
|
Game not found. Send us a message where you can reach us to add it
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
<div className='IBMSMList IBMSMListFeaturedAlt'>
|
||||||
{filteredGames
|
{filteredGames
|
||||||
@ -521,20 +527,14 @@ const GamesResult = ({ searchTerm }: GamesResultProps) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{searchTerm !== '' && filteredGames.length > MAX_GAMES_PER_PAGE && (
|
||||||
<Pagination
|
<Pagination
|
||||||
page={page}
|
page={page}
|
||||||
disabledNext={filteredGames.length <= page * MAX_GAMES_PER_PAGE}
|
disabledNext={filteredGames.length <= page * MAX_GAMES_PER_PAGE}
|
||||||
handlePrev={handlePrev}
|
handlePrev={handlePrev}
|
||||||
handleNext={handleNext}
|
handleNext={handleNext}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
function dedup(event1: NDKEvent, event2: NDKEvent) {
|
|
||||||
// return the newest of the two
|
|
||||||
if (event1.created_at! > event2.created_at!) {
|
|
||||||
return event1
|
|
||||||
}
|
|
||||||
|
|
||||||
return event2
|
|
||||||
}
|
|
||||||
|
3
src/pages/supporters.tsx
Normal file
3
src/pages/supporters.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const SupportersPage = () => {
|
||||||
|
return <h2>WIP</h2>
|
||||||
|
}
|
@ -28,6 +28,8 @@ import { BlogPage } from '../pages/blog'
|
|||||||
import { blogRouteLoader } from '../pages/blog/loader'
|
import { blogRouteLoader } from '../pages/blog/loader'
|
||||||
import { blogRouteAction } from '../pages/blog/action'
|
import { blogRouteAction } from '../pages/blog/action'
|
||||||
import { reportRouteAction } from '../actions/report'
|
import { reportRouteAction } from '../actions/report'
|
||||||
|
import { BackupPage } from 'pages/backup'
|
||||||
|
import { SupportersPage } from 'pages/supporters'
|
||||||
|
|
||||||
export const appRoutes = {
|
export const appRoutes = {
|
||||||
home: '/',
|
home: '/',
|
||||||
@ -51,7 +53,9 @@ export const appRoutes = {
|
|||||||
settingsAdmin: '/settings-admin',
|
settingsAdmin: '/settings-admin',
|
||||||
profile: '/profile/:nprofile?',
|
profile: '/profile/:nprofile?',
|
||||||
feed: '/feed',
|
feed: '/feed',
|
||||||
notifications: '/notifications'
|
notifications: '/notifications',
|
||||||
|
backup: '/backup',
|
||||||
|
supporters: '/supporters'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGamePageRoute = (name: string) =>
|
export const getGamePageRoute = (name: string) =>
|
||||||
@ -185,6 +189,14 @@ export const routerWithNdkContext = (context: NDKContextType) =>
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: appRoutes.backup,
|
||||||
|
element: <BackupPage />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: appRoutes.supporters,
|
||||||
|
element: <SupportersPage />
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '*',
|
path: '*',
|
||||||
element: <NotFoundPage />
|
element: <NotFoundPage />
|
||||||
|
36
src/styles/backup.css
Normal file
36
src/styles/backup.css
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
.backupList {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
grid-gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.backupListLink {
|
||||||
|
transition: ease 0.4s;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 0 8px 0 rgb(0,0,0,0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
/*border: solid 1px rgba(255,255,255,0.1);*/
|
||||||
|
position: relative;
|
||||||
|
color: rgba(255,255,255,0.75);
|
||||||
|
min-height: 150px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.backupListLink:hover {
|
||||||
|
transition: ease 0.4s;
|
||||||
|
text-decoration: unset;
|
||||||
|
color: rgb(255,255,255);
|
||||||
|
transform: scale(1.02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.backupListLinkInside {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
grid-gap: 0px;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
@ -274,3 +274,16 @@ export function orderEventsChronologically(
|
|||||||
|
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives two events and returns the "correct" event to use.
|
||||||
|
* #nip-33
|
||||||
|
*/
|
||||||
|
export default function dedup(event1: NDKEvent, event2: NDKEvent) {
|
||||||
|
// return the newest of the two
|
||||||
|
if (event1.created_at! > event2.created_at!) {
|
||||||
|
return event1
|
||||||
|
}
|
||||||
|
|
||||||
|
return event2
|
||||||
|
}
|
||||||
|
@ -160,3 +160,23 @@ export const parseFormData = <T>(formData: FormData) => {
|
|||||||
export const capitalizeEachWord = (str: string): string => {
|
export const capitalizeEachWord = (str: string): string => {
|
||||||
return str.replace(/\b\w/g, (char) => char.toUpperCase())
|
return str.replace(/\b\w/g, (char) => char.toUpperCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nostr-login - helper function
|
||||||
|
* should only be used as the fallback
|
||||||
|
* user state is not updated before `onAuth` triggers but loaders are faster
|
||||||
|
*/
|
||||||
|
export const getFallbackPubkey = () => {
|
||||||
|
try {
|
||||||
|
// read nostr-login conf from localStorage
|
||||||
|
const stored = window.localStorage.getItem('__nostrlogin_nip46')
|
||||||
|
if (!stored) return
|
||||||
|
|
||||||
|
const info = JSON.parse(stored)
|
||||||
|
if (info && !info.pubkey) return
|
||||||
|
|
||||||
|
return info.pubkey as string
|
||||||
|
} catch {
|
||||||
|
// Silently ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user