Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
846914f
chore: upgrade Next.js from 14.2.25 to 15.5.14; upgrade to React 19; …
Soxasora Apr 5, 2026
ffb119b
Merge branch 'master' into chore/update-nextjs-16
Soxasora Apr 5, 2026
e8fedc8
upgrade Bootstrap to 5.3.8; upgrade react-boostrap to 2.10.10; silenc…
Soxasora Apr 5, 2026
8f7e221
upgrade Next.js to 16.2.2, rename middleware.js to proxy.js
Soxasora Apr 5, 2026
fd7cb96
polyfill URLPattern and add to js-standard lint globals
Soxasora Apr 5, 2026
29ab41b
upgrade to next-plausible 4.0.0; remove PlausibleProvider dead props
Soxasora Apr 5, 2026
0cf9f68
fix: run withPlausibleProxy through webpack instead of treating it as…
Soxasora Apr 5, 2026
da82997
apollo: useLazyQuery now throws AbortError, add errorPolicy 'all' to …
Soxasora Apr 5, 2026
3813e00
apollo migration: remove @client and @defer directives support from A…
Soxasora Apr 6, 2026
4717770
apollo migration: switch now-internal getOperationName with graphql's…
Soxasora Apr 6, 2026
7a6367c
remove Apollo's execute double catch
Soxasora Apr 6, 2026
d556244
remove temporary nodejs nextjs 15 middleware workaround
Soxasora Apr 6, 2026
cb5b2fd
cleanup: linting
Soxasora Apr 6, 2026
41a0307
remove legacyBehavior and passHref, use NextLink as anchor for compon…
Soxasora Apr 8, 2026
2ae1b0d
Merge branch 'master' into chore/update-nextjs-16
Soxasora Apr 9, 2026
96fd1f0
fix: allowedDevOrigins starts by default with NEXT_PUBLIC_URL, new AL…
Soxasora Apr 10, 2026
d7e6c3a
fix: put allowedDevOrigins in the right next.config.js section
Soxasora Apr 10, 2026
5324862
merge master, adapt changes to Apollo Client v4
Soxasora Apr 12, 2026
539b2a5
Merge branch 'master' into chore/update-nextjs-16
huumn Apr 13, 2026
85d3e80
fix: switch back to notifyOnNetworkStatusChange false to get the orig…
Soxasora Apr 14, 2026
1a2b129
remove dangling sub prop
Soxasora Apr 14, 2026
e5c99c6
filter AbortError from useLazyQuery executions
Soxasora Apr 14, 2026
2a21acd
refactor: BaseSuggest with `useQuery` instead of `useLazyQuery`
Soxasora Apr 14, 2026
ed4227b
fix: add back resetSuggestions
Soxasora Apr 14, 2026
a853a2c
refactor: SubMultiSelect with `client.query`
Soxasora Apr 14, 2026
5d338bc
refactor: TerritoryForm `onNameChange` with `client.query`
Soxasora Apr 14, 2026
35020d0
Merge branch 'master' into refactor/lazy-queries-ac4-migration
Soxasora Apr 14, 2026
d2f3b34
fix unsuccessful web merge
Soxasora Apr 15, 2026
00be54e
refactor: `useLexicalUploadFees` with `client.query`
Soxasora Apr 15, 2026
13ff5cb
refactor: Lexical mentions plugin `useSuggestions` with `client.query`
Soxasora Apr 15, 2026
dfb3e15
refactor: `useAutoRetryPayIns` with `client.query`
Soxasora Apr 15, 2026
6fbe41f
refactor: `useCrossposter` `fetchItemData` with `client.query`
Soxasora Apr 15, 2026
b1085e2
refactor: `PostEdit` with `useQuery`, compact logic
Soxasora Apr 15, 2026
c508c67
Merge branch 'master' into refactor/lazy-queries-ac4-migration
Soxasora Apr 15, 2026
4c027df
cleanup: remove console.log from upload plugin
Soxasora Apr 15, 2026
834ae2d
fix: re-implement resetSuggestions correctly
Soxasora Apr 15, 2026
a9606ed
cleanup: add back error handling to `client.query`
Soxasora Apr 15, 2026
5cccc0b
fix: show mention suggestions even if query is empty
Soxasora Apr 15, 2026
15b6524
add error handling to TerritoryForm
Soxasora Apr 15, 2026
69c0da4
fix: suggestions array governed by show status
Soxasora Apr 15, 2026
57e05d4
remove dead nextFetchPolicy option from client.query users
Soxasora Apr 15, 2026
5c79e51
use functional updaters for BaseSuggest index
Soxasora Apr 15, 2026
d52e92e
Merge branch 'master' into refactor/lazy-queries-ac4-migration
huumn Apr 26, 2026
95589d8
revert to useLazyQuery for territory-form and useLexicalUploadFees ho…
Soxasora Apr 27, 2026
8676013
always base the active suggestions index on the current suggestions a…
Soxasora Apr 27, 2026
6961664
restore useLazyQuery in BaseSuggest
Soxasora Apr 27, 2026
f4fae62
Merge branch 'master' into refactor/lazy-queries-ac4-migration
Soxasora Apr 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions components/editor/plugins/mentions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { createPortal } from 'react-dom'
import Dropdown from 'react-bootstrap/Dropdown'
import { useLazyQuery } from '@apollo/client/react'
import { useApolloClient } from '@apollo/client/react'
import { LexicalTypeaheadMenuPlugin, MenuOption } from '@lexical/react/LexicalTypeaheadMenuPlugin'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import useDebounceCallback from '@/components/use-debounce-callback'
Expand All @@ -18,47 +18,47 @@ const MENTION_PATTERN = /(^|\s|\()([@~]\w{0,75})$/
const MAX_SUGGESTIONS = 5
const SUGGESTION_DEBOUNCE_MS = 150

function getSuggestionLookup (trigger, getUserSuggestions, getSubSuggestions) {
function getSuggestionLookup (trigger) {
switch (trigger) {
case '@':
return { getSuggestions: getUserSuggestions, itemsField: 'userSuggestions' }
return { query: USER_SUGGESTIONS, itemsField: 'userSuggestions' }
case '~':
return { getSuggestions: getSubSuggestions, itemsField: 'subSuggestions' }
return { query: SUB_SUGGESTIONS, itemsField: 'subSuggestions' }
default:
return null
}
}

/** takes the full \@user or \~sub and fetches the suggestions */
function useSuggestions ({ query }) {
const client = useApolloClient()
const [suggestions, setSuggestions] = useState([])
const requestIdRef = useRef(0)

const [getUserSuggestions] = useLazyQuery(USER_SUGGESTIONS)
const [getSubSuggestions] = useLazyQuery(SUB_SUGGESTIONS)
const setCurrentSuggestions = useCallback((requestId, nextSuggestions = []) => {
if (requestId === requestIdRef.current) {
setSuggestions(nextSuggestions)
}
}, [])

const fetchSuggestions = useDebounceCallback(async (nextQuery, requestId) => {
const lookup = getSuggestionLookup(nextQuery[0], getUserSuggestions, getSubSuggestions)
const lookup = getSuggestionLookup(nextQuery[0])

if (!lookup) {
setCurrentSuggestions(requestId)
return
}

try {
const { data } = await lookup.getSuggestions({
const { data } = await client.query({
query: lookup.query,
variables: { q: nextQuery.slice(1), limit: MAX_SUGGESTIONS }
})
setCurrentSuggestions(requestId, data?.[lookup.itemsField] || [])
} catch {
setCurrentSuggestions(requestId)
}
}, SUGGESTION_DEBOUNCE_MS, [getUserSuggestions, getSubSuggestions, setCurrentSuggestions])
}, SUGGESTION_DEBOUNCE_MS, [client, setCurrentSuggestions])

useEffect(() => {
if (!query) {
Expand Down
5 changes: 2 additions & 3 deletions components/editor/plugins/upload.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useEffect, useRef, useCallback } from 'react'
import { isAbortError } from '@/lib/error'
import {
COMMAND_PRIORITY_EDITOR,
$getRoot,
Expand Down Expand Up @@ -29,6 +28,7 @@ import styles from '@/lib/lexical/theme/editor.module.css'
import { $insertTextAtSelection } from '@/lib/lexical/utils'
import { isMarkdownMode } from '@/lib/lexical/commands/utils'
import { $createMediaNode, MediaNode } from '@/lib/lexical/nodes/content/media'
import { isAbortError } from '@/lib/error'

// submit disabled reason for upload
export const UPLOAD_SUBMIT_DISABLED_REASON = 'upload'
Expand Down Expand Up @@ -263,8 +263,7 @@ function useLexicalUploadFees (editor) {
const { merge } = useFeeButton()

const [updateUploadFees] = useLazyQuery(UPLOAD_FEES_QUERY, {
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache'
fetchPolicy: 'no-cache'
})

const handleUploadFeesData = useCallback(({ data }) => {
Expand Down
3 changes: 2 additions & 1 deletion components/form.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Button from 'react-bootstrap/Button'
import InputGroup from 'react-bootstrap/InputGroup'
import BootstrapForm from 'react-bootstrap/Form'
import { isAbortError } from '@/lib/error'
import { Formik, Form as FormikForm, useFormikContext, useField, FieldArray } from 'formik'
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import copy from 'clipboard-copy'
Expand Down Expand Up @@ -33,6 +32,7 @@ import dynamic from 'next/dynamic'
import { useIsClient } from './use-client'
import PageLoading from './page-loading'
import { SNEditor } from './editor'
import { isAbortError } from '@/lib/error'
export { MultiSelect } from './multi-select'
export class SessionRequiredError extends Error {
constructor () {
Expand Down Expand Up @@ -489,6 +489,7 @@ export function BaseSuggest ({
resetSuggestions()
}
}, [query, resetSuggestions, getSuggestions])

const onKeyDown = useCallback(e => {
switch (e.code) {
case 'ArrowUp':
Expand Down
15 changes: 9 additions & 6 deletions components/payIn/hooks/use-auto-retry-pay-ins.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { usePreferredSendProtocolId, useWalletPayment } from '@/wallets/client/hooks'
import { isAbortError } from '@/lib/error'
import usePayInHelper from './use-pay-in-helper'
import { useLazyQuery } from '@apollo/client/react'
import { useApolloClient } from '@apollo/client/react'
import { FAILED_PAY_INS } from '@/fragments/payIn'
import { useMe } from '@/components/me'
import { useEffect } from 'react'
Expand All @@ -12,7 +11,7 @@ export function useAutoRetryPayIns () {
const waitForWalletPayment = useWalletPayment()
const sendProtocolId = usePreferredSendProtocolId()
const payInHelper = usePayInHelper()
const [getFailedPayIns] = useLazyQuery(FAILED_PAY_INS, { fetchPolicy: 'network-only', nextFetchPolicy: 'network-only', errorPolicy: 'all' })
const client = useApolloClient()
const { me } = useMe()

useEffect(() => {
Expand All @@ -39,11 +38,15 @@ export function useAutoRetryPayIns () {

let failedPayIns
try {
const { data, error } = await getFailedPayIns()
const { data, error } = await client.query({
query: FAILED_PAY_INS,
fetchPolicy: 'network-only',
errorPolicy: 'all'
})
if (error) throw error
failedPayIns = data.failedPayIns
} catch (err) {
!isAbortError(err) && console.error('failed to fetch invoices to retry:', err)
Comment thread
Soxasora marked this conversation as resolved.
console.error('failed to fetch invoices to retry:', err)
return
}

Expand Down Expand Up @@ -80,7 +83,7 @@ export function useAutoRetryPayIns () {

queuePoll()
return stopPolling
}, [me?.id, sendProtocolId, getFailedPayIns, payInHelper, waitForWalletPayment])
}, [me?.id, sendProtocolId, client, payInHelper, waitForWalletPayment])
}

export function isAutoRetryEligiblePayIn (payIn) {
Expand Down
12 changes: 7 additions & 5 deletions components/sub-select.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useEffect, useState } from 'react'
import { isAbortError } from '@/lib/error'
import { useRouter } from 'next/router'
import { MultiSelect, Select } from './form'
import { EXTRA_LONG_POLL_INTERVAL_MS, SSR } from '@/lib/constants'
import { ACTIVE_SUBS, SUB_FULL } from '@/fragments/subs'
import { useLazyQuery, useQuery } from '@apollo/client/react'
import { useApolloClient, useQuery } from '@apollo/client/react'
import styles from './sub-select.module.css'
import { useMe } from './me'
import { useShowModal } from './modal'
Expand Down Expand Up @@ -141,6 +140,7 @@ export default function SubSelect ({ prependSubs, sub, onChange, size, appendSub

export function SubMultiSelect ({ prependSubs, subs, onChange, size, appendSubs, filterSubs, className, ...props }) {
const router = useRouter()
const client = useApolloClient()
const activeSubs = useSubs({ prependSubs, subs, filterSubs, appendSubs })
const valueProps = props.noForm
? {
Expand All @@ -151,16 +151,18 @@ export function SubMultiSelect ({ prependSubs, subs, onChange, size, appendSubs,
}

const showModal = useShowModal()
const [getSub] = useLazyQuery(SUB_FULL)

const handleTerritoryClick = async (subName) => {
try {
const { data } = await getSub({ variables: { sub: subName } })
const { data } = await client.query({
query: SUB_FULL,
variables: { sub: subName }
})
if (data?.sub) {
showModal(() => <TerritoryInfo sub={data.sub} includeLink />)
}
} catch (err) {
!isAbortError(err) && console.error(err)
console.error(err)
}
}

Expand Down
2 changes: 1 addition & 1 deletion components/territory-form.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import AccordianItem from './accordian-item'
import { isAbortError } from '@/lib/error'
import { Col, InputGroup, Row, Form as BootstrapForm, Badge } from 'react-bootstrap'
import { Checkbox, CheckboxGroup, Form, Input, SNInput, Range } from './form'
import { useFormikContext } from 'formik'
Expand All @@ -20,6 +19,7 @@ import Link from 'next/link'
import usePayInMutation from '@/components/payIn/hooks/use-pay-in-mutation'
import { UNARCHIVE_TERRITORY, UPSERT_SUB } from '@/fragments/payIn'
import LinkExternal from '@/svgs/link-external.svg'
import { isAbortError } from '@/lib/error'

function SatFilterRanges () {
const { values } = useFormikContext()
Expand Down
34 changes: 16 additions & 18 deletions components/use-crossposter.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useCallback } from 'react'
import { isAbortError } from '@/lib/error'
import { useToast } from './toast'
import { Button } from 'react-bootstrap'
import Nostr, { DEFAULT_CROSSPOSTING_RELAYS } from '@/lib/nostr'
import { gql } from '@apollo/client'
import { useLazyQuery, useMutation, useQuery } from '@apollo/client/react'
import { useApolloClient, useMutation, useQuery } from '@apollo/client/react'
import { SETTINGS } from '@/fragments/users'
import { ITEM_FULL_FIELDS, POLL_FIELDS } from '@/fragments/items'

Expand Down Expand Up @@ -85,24 +84,11 @@ function bountyToEvent (item) {

export default function useCrossposter () {
const toaster = useToast()
const client = useApolloClient()
const { data } = useQuery(SETTINGS)
const userRelays = data?.settings?.privates?.nostrRelays || []
const relays = [...DEFAULT_CROSSPOSTING_RELAYS, ...userRelays]

const [fetchItem] = useLazyQuery(
gql`
${ITEM_FULL_FIELDS}
${POLL_FIELDS}
query Item($id: ID!) {
item(id: $id) {
...ItemFullFields
...PollFields
}
}`, {
fetchPolicy: 'no-cache'
}
)

const [updateNoteId] = useMutation(
gql`
mutation updateNoteId($id: ID!, $noteId: String!) {
Expand Down Expand Up @@ -186,11 +172,23 @@ export default function useCrossposter () {

const fetchItemData = async (itemId) => {
try {
const { data } = await fetchItem({ variables: { id: itemId } })
const { data } = await client.query({
query: gql`
${ITEM_FULL_FIELDS}
${POLL_FIELDS}
query Item($id: ID!) {
item(id: $id) {
...ItemFullFields
...PollFields
}
}`,
variables: { id: itemId },
fetchPolicy: 'no-cache'
})

return data?.item
} catch (e) {
!isAbortError(e) && console.error(e)
console.error(e)
return null
}
}
Expand Down
61 changes: 20 additions & 41 deletions pages/items/[id]/edit.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { ITEM } from '@/fragments/items'
import { isAbortError } from '@/lib/error'
import { getGetServerSideProps } from '@/api/ssrApollo'
import { DiscussionForm } from '@/components/discussion-form'
import { LinkForm } from '@/components/link-form'
import { CenterLayout } from '@/components/layout'
import JobForm from '@/components/job-form'
import { PollForm } from '@/components/poll-form'
import { BountyForm } from '@/components/bounty-form'
import { useEffect, useState } from 'react'
import { useLazyQuery, useQuery } from '@apollo/client/react'
import { useMemo, useState } from 'react'
import { useQuery } from '@apollo/client/react'
import { useRouter } from 'next/router'
import PageLoading from '@/components/page-loading'
import { FeeButtonProvider } from '@/components/fee-button'
Expand All @@ -26,49 +25,29 @@ export const getServerSideProps = getGetServerSideProps({
export default function PostEdit ({ ssrData }) {
const router = useRouter()
const { data } = useQuery(ITEM, { variables: { id: router.query.id } })
const [fetchSubs] = useLazyQuery(SUBS)
if (!data && !ssrData) return <PageLoading />

const { item } = data || ssrData
const [subs, setSubs] = useState(item.subNames)
const [baseLineItems, setBaseLineItems] = useState({})

useEffect(() => {
const territoryAddPrefix = 'territory-add-'
const addedSubs = subsDiff(subs, item.subNames)
if (!addedSubs.length) {
setBaseLineItems(prev => Object.entries(prev).reduce((acc, [key, value]) => {
if (!key.startsWith(territoryAddPrefix)) {
acc[key] = value
}
return acc
}, {}))
return
}
fetchSubs({ variables: { subNames: addedSubs } }).then(res => {
setBaseLineItems(prev => {
const newBaseLineItems = Object.entries(prev).reduce((acc, [key, value]) => {
if (!key.startsWith(territoryAddPrefix)) {
acc[key] = value
}
return acc
}, {})
const territoryAdds = res.data.subs.reduce((acc, sub) => ({
...acc,
[`${territoryAddPrefix}${sub.name}`]: {
label: `~${sub.name} post`,
term: `+ ${sub.baseCost}`,
op: '+',
modifier: cost => cost + sub.baseCost
}
}), {})
return {
...newBaseLineItems,
...territoryAdds
}
})
}).catch(err => !isAbortError(err) && console.error(err))
}, [subs, fetchSubs])
const addedSubs = useMemo(() => subsDiff(subs, item.subNames), [subs, item.subNames])
const { data: subsData } = useQuery(SUBS, {
variables: { subNames: addedSubs },
skip: !addedSubs.length
})
Comment thread
cursor[bot] marked this conversation as resolved.

const baseLineItems = useMemo(() => {
if (!addedSubs.length || !subsData?.subs) return {}
return subsData.subs.reduce((acc, sub) => ({
...acc,
[`territory-add-${sub.name}`]: {
label: `~${sub.name} post`,
term: `+ ${sub.baseCost}`,
op: '+',
modifier: cost => cost + sub.baseCost
}
}), {})
}, [addedSubs, subsData])

const [,, editThreshold] = useCanEdit(item)
const EditInfo = editThreshold && item.payIn?.payInState === 'PAID'
Expand Down
Loading