maintage pagination and other state on back button
This commit is contained in:
parent
1a0803a594
commit
7efc86427d
@ -169,9 +169,7 @@ export default {
|
|||||||
throw new AuthenticationError('you must be logged in')
|
throw new AuthenticationError('you must be logged in')
|
||||||
}
|
}
|
||||||
|
|
||||||
await models.user.update({ where: { id: me.id }, data })
|
return await models.user.update({ where: { id: me.id }, data })
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
},
|
||||||
setWalkthrough: async (parent, { upvotePopover, tipPopover }, { me, models }) => {
|
setWalkthrough: async (parent, { upvotePopover, tipPopover }, { me, models }) => {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
|
@ -35,8 +35,20 @@ export default async function getSSRApolloClient (req, me = null) {
|
|||||||
|
|
||||||
export function getGetServerSideProps (query, variables = null, notFoundFunc, requireVar) {
|
export function getGetServerSideProps (query, variables = null, notFoundFunc, requireVar) {
|
||||||
return async function ({ req, query: params }) {
|
return async function ({ req, query: params }) {
|
||||||
const client = await getSSRApolloClient(req)
|
const { nodata, ...realParams } = params
|
||||||
const vars = { ...params, ...variables }
|
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]) {
|
if (requireVar && !vars[requireVar]) {
|
||||||
return {
|
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 = {}
|
let error = null; let data = null; let props = {}
|
||||||
if (query) {
|
if (query) {
|
||||||
({ error, data } = await client.query({
|
({ error, data } = await client.query({
|
||||||
@ -60,7 +73,7 @@ export function getGetServerSideProps (query, variables = null, notFoundFunc, re
|
|||||||
props = {
|
props = {
|
||||||
apollo: {
|
apollo: {
|
||||||
query: print(query),
|
query: print(query),
|
||||||
variables: { ...params, ...variables }
|
variables: vars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ export default gql`
|
|||||||
setName(name: String!): Boolean
|
setName(name: String!): Boolean
|
||||||
setSettings(tipDefault: Int!, noteItemSats: Boolean!, noteEarning: Boolean!,
|
setSettings(tipDefault: Int!, noteItemSats: Boolean!, noteEarning: Boolean!,
|
||||||
noteAllDescendants: Boolean!, noteMentions: Boolean!, noteDeposits: 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!
|
setPhoto(photoId: ID!): Int!
|
||||||
upsertBio(bio: String!): User!
|
upsertBio(bio: String!): User!
|
||||||
setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean
|
setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean
|
||||||
|
@ -96,9 +96,11 @@ export default function UserHeader ({ user }) {
|
|||||||
if (error) {
|
if (error) {
|
||||||
throw new Error({ message: error.toString() })
|
throw new Error({ message: error.toString() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { nodata, ...query } = router.query
|
||||||
router.replace({
|
router.replace({
|
||||||
pathname: router.pathname,
|
pathname: router.pathname,
|
||||||
query: { ...router.query, name }
|
query: { ...query, name }
|
||||||
})
|
})
|
||||||
|
|
||||||
client.writeFragment({
|
client.writeFragment({
|
||||||
|
@ -54,9 +54,8 @@ export const ME_SSR = gql`
|
|||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
export const SETTINGS = gql`
|
export const SETTINGS_FIELDS = gql`
|
||||||
{
|
fragment SettingsFields on User {
|
||||||
settings {
|
|
||||||
tipDefault
|
tipDefault
|
||||||
noteItemSats
|
noteItemSats
|
||||||
noteEarning
|
noteEarning
|
||||||
@ -72,9 +71,31 @@ export const SETTINGS = gql`
|
|||||||
twitter
|
twitter
|
||||||
github
|
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 =
|
export const NAME_QUERY =
|
||||||
gql`
|
gql`
|
||||||
query nameAvailable($name: String!) {
|
query nameAvailable($name: String!) {
|
||||||
@ -164,6 +185,11 @@ export const USER_WITH_POSTS = gql`
|
|||||||
cursor
|
cursor
|
||||||
items {
|
items {
|
||||||
...ItemFields
|
...ItemFields
|
||||||
|
position
|
||||||
|
}
|
||||||
|
pins {
|
||||||
|
...ItemFields
|
||||||
|
position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
@ -79,7 +79,7 @@ export default function getApolloClient () {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
notifications: {
|
notifications: {
|
||||||
keyArgs: false,
|
keyArgs: ['inc'],
|
||||||
merge (existing, incoming) {
|
merge (existing, incoming) {
|
||||||
if (isFirstPage(incoming.cursor, existing?.notifications)) {
|
if (isFirstPage(incoming.cursor, existing?.notifications)) {
|
||||||
return incoming
|
return incoming
|
||||||
|
@ -10,7 +10,7 @@ export const getServerSideProps = getGetServerSideProps(USER_WITH_POSTS)
|
|||||||
|
|
||||||
export default function UserPosts ({ data: { user, items: { items, cursor } } }) {
|
export default function UserPosts ({ data: { user, items: { items, cursor } } }) {
|
||||||
const { data } = useQuery(USER_WITH_POSTS,
|
const { data } = useQuery(USER_WITH_POSTS,
|
||||||
{ variables: { name: user.name } })
|
{ variables: { name: user.name, sort: 'user' } })
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
({ user, items: { items, cursor } } = data)
|
({ user, items: { items, cursor } } = data)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import '../styles/globals.scss'
|
import '../styles/globals.scss'
|
||||||
import { ApolloProvider, gql } from '@apollo/client'
|
import { ApolloProvider, gql, useQuery } from '@apollo/client'
|
||||||
import { Provider } from 'next-auth/client'
|
import { Provider } from 'next-auth/client'
|
||||||
import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
|
import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
|
||||||
import { MeProvider } from '../components/me'
|
import { MeProvider } from '../components/me'
|
||||||
@ -10,26 +10,63 @@ import getApolloClient from '../lib/apollo'
|
|||||||
import NextNProgress from 'nextjs-progressbar'
|
import NextNProgress from 'nextjs-progressbar'
|
||||||
import { PriceProvider } from '../components/price'
|
import { PriceProvider } from '../components/price'
|
||||||
import Head from 'next/head'
|
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 } }) {
|
function MyApp ({ Component, pageProps: { session, ...props } }) {
|
||||||
const client = getApolloClient()
|
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
|
If we are on the client, we populate the apollo cache with the
|
||||||
ssr data
|
ssr data
|
||||||
*/
|
*/
|
||||||
if (typeof window !== 'undefined') {
|
const { apollo, data, me, price } = props
|
||||||
const { apollo, data } = props
|
if (typeof window !== 'undefined' && apollo && data) {
|
||||||
if (apollo) {
|
|
||||||
client.writeQuery({
|
client.writeQuery({
|
||||||
query: gql`${apollo.query}`,
|
query: gql`${apollo.query}`,
|
||||||
data: data,
|
data: data,
|
||||||
variables: apollo.variables
|
variables: apollo.variables
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const { me, price } = props
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -54,7 +91,9 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
|
|||||||
<FundErrorModal />
|
<FundErrorModal />
|
||||||
<ItemActProvider>
|
<ItemActProvider>
|
||||||
<ItemActModal />
|
<ItemActModal />
|
||||||
<Component {...props} />
|
{data || !apollo?.query
|
||||||
|
? <Component {...props} />
|
||||||
|
: <CSRWrapper Component={Component} {...props} />}
|
||||||
</ItemActProvider>
|
</ItemActProvider>
|
||||||
</FundErrorProvider>
|
</FundErrorProvider>
|
||||||
</LightningProvider>
|
</LightningProvider>
|
||||||
|
@ -9,7 +9,7 @@ import LoginButton from '../components/login-button'
|
|||||||
import { signIn } from 'next-auth/client'
|
import { signIn } from 'next-auth/client'
|
||||||
import ModalButton from '../components/modal-button'
|
import ModalButton from '../components/modal-button'
|
||||||
import { LightningAuth } from '../components/lightning-auth'
|
import { LightningAuth } from '../components/lightning-auth'
|
||||||
import { SETTINGS } from '../fragments/users'
|
import { SETTINGS, SET_SETTINGS } from '../fragments/users'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import Info from '../components/info'
|
import Info from '../components/info'
|
||||||
|
|
||||||
@ -28,16 +28,18 @@ export const WarningSchema = Yup.object({
|
|||||||
|
|
||||||
export default function Settings ({ data: { settings } }) {
|
export default function Settings ({ data: { settings } }) {
|
||||||
const [success, setSuccess] = useState()
|
const [success, setSuccess] = useState()
|
||||||
const [setSettings] = useMutation(
|
const [setSettings] = useMutation(SET_SETTINGS, {
|
||||||
gql`
|
update (cache, { data: { setSettings } }) {
|
||||||
mutation setSettings($tipDefault: Int!, $noteItemSats: Boolean!, $noteEarning: Boolean!,
|
cache.modify({
|
||||||
$noteAllDescendants: Boolean!, $noteMentions: Boolean!, $noteDeposits: Boolean!,
|
id: 'ROOT_QUERY',
|
||||||
$noteInvites: Boolean!, $noteJobIndicator: Boolean!, $hideInvoiceDesc: Boolean!) {
|
fields: {
|
||||||
setSettings(tipDefault: $tipDefault, noteItemSats: $noteItemSats,
|
settings () {
|
||||||
noteEarning: $noteEarning, noteAllDescendants: $noteAllDescendants,
|
return setSettings
|
||||||
noteMentions: $noteMentions, noteDeposits: $noteDeposits, noteInvites: $noteInvites,
|
}
|
||||||
noteJobIndicator: $noteJobIndicator, hideInvoiceDesc: $hideInvoiceDesc)
|
}
|
||||||
}`
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const { data } = useQuery(SETTINGS)
|
const { data } = useQuery(SETTINGS)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user