maintage pagination and other state on back button

This commit is contained in:
keyan 2022-09-06 08:01:49 -05:00
parent 1a0803a594
commit 7efc86427d
9 changed files with 117 additions and 37 deletions

View File

@ -169,9 +169,7 @@ export default {
throw new AuthenticationError('you must be logged in')
}
await models.user.update({ where: { id: me.id }, data })
return true
return await models.user.update({ where: { id: me.id }, data })
},
setWalkthrough: async (parent, { upvotePopover, tipPopover }, { me, models }) => {
if (!me) {

View File

@ -35,8 +35,20 @@ export default async function getSSRApolloClient (req, me = null) {
export function getGetServerSideProps (query, variables = null, notFoundFunc, requireVar) {
return async function ({ req, query: params }) {
const client = await getSSRApolloClient(req)
const vars = { ...params, ...variables }
const { nodata, ...realParams } = params
const vars = { ...realParams, ...variables }
// we want to use client-side cache
if (nodata && query) {
return {
props: {
apollo: {
query: print(query),
variables: vars
}
}
}
}
if (requireVar && !vars[requireVar]) {
return {
@ -44,6 +56,7 @@ export function getGetServerSideProps (query, variables = null, notFoundFunc, re
}
}
const client = await getSSRApolloClient(req)
let error = null; let data = null; let props = {}
if (query) {
({ error, data } = await client.query({
@ -60,7 +73,7 @@ export function getGetServerSideProps (query, variables = null, notFoundFunc, re
props = {
apollo: {
query: print(query),
variables: { ...params, ...variables }
variables: vars
}
}
}

View File

@ -31,7 +31,7 @@ export default gql`
setName(name: String!): Boolean
setSettings(tipDefault: Int!, noteItemSats: Boolean!, noteEarning: Boolean!,
noteAllDescendants: Boolean!, noteMentions: Boolean!, noteDeposits: Boolean!,
noteInvites: Boolean!, noteJobIndicator: Boolean!, hideInvoiceDesc: Boolean!): Boolean
noteInvites: Boolean!, noteJobIndicator: Boolean!, hideInvoiceDesc: Boolean!): User
setPhoto(photoId: ID!): Int!
upsertBio(bio: String!): User!
setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean

View File

@ -96,9 +96,11 @@ export default function UserHeader ({ user }) {
if (error) {
throw new Error({ message: error.toString() })
}
const { nodata, ...query } = router.query
router.replace({
pathname: router.pathname,
query: { ...router.query, name }
query: { ...query, name }
})
client.writeFragment({

View File

@ -54,9 +54,8 @@ export const ME_SSR = gql`
}
}`
export const SETTINGS = gql`
{
settings {
export const SETTINGS_FIELDS = gql`
fragment SettingsFields on User {
tipDefault
noteItemSats
noteEarning
@ -72,9 +71,31 @@ export const SETTINGS = gql`
twitter
github
}
}`
export const SETTINGS = gql`
${SETTINGS_FIELDS}
{
settings {
...SettingsFields
}
}`
export const SET_SETTINGS =
gql`
${SETTINGS_FIELDS}
mutation setSettings($tipDefault: Int!, $noteItemSats: Boolean!, $noteEarning: Boolean!,
$noteAllDescendants: Boolean!, $noteMentions: Boolean!, $noteDeposits: Boolean!,
$noteInvites: Boolean!, $noteJobIndicator: Boolean!, $hideInvoiceDesc: Boolean!) {
setSettings(tipDefault: $tipDefault, noteItemSats: $noteItemSats,
noteEarning: $noteEarning, noteAllDescendants: $noteAllDescendants,
noteMentions: $noteMentions, noteDeposits: $noteDeposits, noteInvites: $noteInvites,
noteJobIndicator: $noteJobIndicator, hideInvoiceDesc: $hideInvoiceDesc) {
...SettingsFields
}
}
`
export const NAME_QUERY =
gql`
query nameAvailable($name: String!) {
@ -164,6 +185,11 @@ export const USER_WITH_POSTS = gql`
cursor
items {
...ItemFields
position
}
pins {
...ItemFields
position
}
}
}`

View File

@ -79,7 +79,7 @@ export default function getApolloClient () {
}
},
notifications: {
keyArgs: false,
keyArgs: ['inc'],
merge (existing, incoming) {
if (isFirstPage(incoming.cursor, existing?.notifications)) {
return incoming

View File

@ -10,7 +10,7 @@ export const getServerSideProps = getGetServerSideProps(USER_WITH_POSTS)
export default function UserPosts ({ data: { user, items: { items, cursor } } }) {
const { data } = useQuery(USER_WITH_POSTS,
{ variables: { name: user.name } })
{ variables: { name: user.name, sort: 'user' } })
if (data) {
({ user, items: { items, cursor } } = data)

View File

@ -1,5 +1,5 @@
import '../styles/globals.scss'
import { ApolloProvider, gql } from '@apollo/client'
import { ApolloProvider, gql, useQuery } from '@apollo/client'
import { Provider } from 'next-auth/client'
import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
import { MeProvider } from '../components/me'
@ -10,27 +10,64 @@ import getApolloClient from '../lib/apollo'
import NextNProgress from 'nextjs-progressbar'
import { PriceProvider } from '../components/price'
import Head from 'next/head'
import { useRouter } from 'next/dist/client/router'
import { useEffect } from 'react'
import Moon from '../svgs/moon-fill.svg'
import Layout from '../components/layout'
function CSRWrapper ({ Component, apollo, ...props }) {
const { data, error } = useQuery(gql`${apollo.query}`, { variables: apollo.variables, fetchPolicy: 'cache-first' })
if (error) {
return (
<div className='d-flex font-weight-bold justify-content-center mt-3 mb-1'>
{error.toString()}
</div>
)
}
if (!data) {
return (
<Layout>
<div className='d-flex justify-content-center mt-3 mb-1'>
<Moon className='spin fill-grey' />
</div>
</Layout>
)
}
return <Component {...props} data={data} />
}
function MyApp ({ Component, pageProps: { session, ...props } }) {
const client = getApolloClient()
const router = useRouter()
useEffect(async () => {
// HACK: 'cause there's no way to tell Next to skip SSR
// So every page load, we modify the route in browser history
// to point to the same page but without SSR, ie ?nodata=true
// this nodata var will get passed to the server on back/foward and
// 1. prevent data from reloading and 2. perserve scroll
// (2) is not possible while intercepting nav with beforePopState
router.replace({
pathname: router.pathname,
query: { ...router.query, nodata: true }
}, router.asPath, { ...router.options, scroll: false })
}, [router.asPath])
/*
If we are on the client, we populate the apollo cache with the
ssr data
*/
if (typeof window !== 'undefined') {
const { apollo, data } = props
if (apollo) {
client.writeQuery({
query: gql`${apollo.query}`,
data: data,
variables: apollo.variables
})
}
const { apollo, data, me, price } = props
if (typeof window !== 'undefined' && apollo && data) {
client.writeQuery({
query: gql`${apollo.query}`,
data: data,
variables: apollo.variables
})
}
const { me, price } = props
return (
<>
<NextNProgress
@ -54,7 +91,9 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
<FundErrorModal />
<ItemActProvider>
<ItemActModal />
<Component {...props} />
{data || !apollo?.query
? <Component {...props} />
: <CSRWrapper Component={Component} {...props} />}
</ItemActProvider>
</FundErrorProvider>
</LightningProvider>

View File

@ -9,7 +9,7 @@ import LoginButton from '../components/login-button'
import { signIn } from 'next-auth/client'
import ModalButton from '../components/modal-button'
import { LightningAuth } from '../components/lightning-auth'
import { SETTINGS } from '../fragments/users'
import { SETTINGS, SET_SETTINGS } from '../fragments/users'
import { useRouter } from 'next/router'
import Info from '../components/info'
@ -28,16 +28,18 @@ export const WarningSchema = Yup.object({
export default function Settings ({ data: { settings } }) {
const [success, setSuccess] = useState()
const [setSettings] = useMutation(
gql`
mutation setSettings($tipDefault: Int!, $noteItemSats: Boolean!, $noteEarning: Boolean!,
$noteAllDescendants: Boolean!, $noteMentions: Boolean!, $noteDeposits: Boolean!,
$noteInvites: Boolean!, $noteJobIndicator: Boolean!, $hideInvoiceDesc: Boolean!) {
setSettings(tipDefault: $tipDefault, noteItemSats: $noteItemSats,
noteEarning: $noteEarning, noteAllDescendants: $noteAllDescendants,
noteMentions: $noteMentions, noteDeposits: $noteDeposits, noteInvites: $noteInvites,
noteJobIndicator: $noteJobIndicator, hideInvoiceDesc: $hideInvoiceDesc)
}`
const [setSettings] = useMutation(SET_SETTINGS, {
update (cache, { data: { setSettings } }) {
cache.modify({
id: 'ROOT_QUERY',
fields: {
settings () {
return setSettings
}
}
})
}
}
)
const { data } = useQuery(SETTINGS)