Compare commits

...

14 Commits

Author SHA1 Message Date
k00b 1d3ab23ec4 cached fetcher delete key 2024-10-16 14:43:11 -05:00
k00b 1645c2aabf avoid dev refresh of lnd 2024-10-16 14:43:00 -05:00
Keyan ec8e775ae6
Merge pull request #1477 from stackernews/upgrade-deps
Upgrade deps
2024-10-15 12:47:56 -05:00
k00b 031d589686 disable next telemetry 2024-10-15 12:13:40 -05:00
Keyan 7d139faca1
Merge branch 'master' into upgrade-deps 2024-10-15 11:34:55 -05:00
k00b 4b18498651 hide cowboy hat -> essentials 2024-10-14 17:52:40 -05:00
k00b 2562999e85 fix mathjax single dollar conflicts 2024-10-13 10:08:54 -05:00
k00b fac70a0b94 npm audit 2024-10-12 18:28:16 -05:00
k00b 81897461e3 fix qrcode display after upgrade 2024-10-12 18:06:07 -05:00
k00b 6a8b823f9f upgrade qr code scanner and fix #1476 2024-10-12 18:06:07 -05:00
k00b f9ed1ee6f5 upgrade non-(apparently)-breaking major versions 2024-10-12 18:06:07 -05:00
k00b ff3ad7676d upgrade minor dep versions 2024-10-12 18:06:07 -05:00
k00b 9a6a167dd4 upgrade patch versions 2024-10-12 18:06:07 -05:00
k00b 021a13d21e fix anon badge 2024-10-12 18:05:45 -05:00
17 changed files with 3975 additions and 3034 deletions

View File

@ -165,4 +165,6 @@ LNBITS_WEB_PORT=5001
# CPU shares for each category # CPU shares for each category
CPU_SHARES_IMPORTANT=1024 CPU_SHARES_IMPORTANT=1024
CPU_SHARES_MODERATE=512 CPU_SHARES_MODERATE=512
CPU_SHARES_LOW=256 CPU_SHARES_LOW=256
NEXT_TELEMETRY_DISABLED=1

View File

@ -22,3 +22,4 @@ GRAPHQL_SLOW_LOGS_MS=50
DB_APP_CONNECTION_LIMIT=4 DB_APP_CONNECTION_LIMIT=4
DB_WORKER_CONNECTION_LIMIT=2 DB_WORKER_CONNECTION_LIMIT=2
DB_TRANSACTION_TIMEOUT=10000 DB_TRANSACTION_TIMEOUT=10000
NEXT_TELEMETRY_DISABLED=1

View File

@ -2,11 +2,13 @@ import { cachedFetcher } from '@/lib/fetch'
import { toPositiveNumber } from '@/lib/validate' import { toPositiveNumber } from '@/lib/validate'
import { authenticatedLndGrpc, getIdentity, getHeight, getWalletInfo, getNode } from 'ln-service' import { authenticatedLndGrpc, getIdentity, getHeight, getWalletInfo, getNode } from 'ln-service'
const { lnd } = authenticatedLndGrpc({ const lnd = global.lnd || authenticatedLndGrpc({
cert: process.env.LND_CERT, cert: process.env.LND_CERT,
macaroon: process.env.LND_MACAROON, macaroon: process.env.LND_MACAROON,
socket: process.env.LND_SOCKET socket: process.env.LND_SOCKET
}) }).lnd
if (process.env.NODE_ENV === 'development') global.lnd = lnd
// Check LND GRPC connection // Check LND GRPC connection
getWalletInfo({ lnd }, (err, result) => { getWalletInfo({ lnd }, (err, result) => {

View File

@ -1024,6 +1024,20 @@ export default {
return user.streak return user.streak
}, },
gunStreak: async (user, args, { models }) => {
if (user.hideCowboyHat) {
return null
}
return user.gunStreak
},
horseStreak: async (user, args, { models }) => {
if (user.hideCowboyHat) {
return null
}
return user.horseStreak
},
maxStreak: async (user, args, { models }) => { maxStreak: async (user, args, { models }) => {
if (user.hideCowboyHat) { if (user.hideCowboyHat) {
return null return null

View File

@ -1,6 +1,6 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react' import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import cookie from 'cookie' import * as cookie from 'cookie'
import { useMe } from '@/components/me' import { useMe } from '@/components/me'
import { USER_ID, SSR } from '@/lib/constants' import { USER_ID, SSR } from '@/lib/constants'
import { USER } from '@/fragments/users' import { USER } from '@/fragments/users'

View File

@ -1,4 +1,3 @@
import Badge from 'react-bootstrap/Badge'
import OverlayTrigger from 'react-bootstrap/OverlayTrigger' import OverlayTrigger from 'react-bootstrap/OverlayTrigger'
import Tooltip from 'react-bootstrap/Tooltip' import Tooltip from 'react-bootstrap/Tooltip'
import CowboyHatIcon from '@/svgs/cowboy.svg' import CowboyHatIcon from '@/svgs/cowboy.svg'
@ -30,12 +29,7 @@ export default function Badges ({ user, badge, className = 'ms-1', badgeClassNam
if (Number(user.id) === USER_ID.anon) { if (Number(user.id) === USER_ID.anon) {
return ( return (
<BadgeTooltip overlayText='anonymous'> <BadgeTooltip overlayText='anonymous'>
{badge <span className={className}><AnonIcon className={`${badgeClassName} align-middle`} height={height} width={width} /></span>
? (
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
<AnonIcon className={`${badgeClassName} fill-dark align-middle`} height={height} width={width} />
</Badge>)
: <span><AnonIcon className={`${badgeClassName} align-middle`} height={height} width={width} /></span>}
</BadgeTooltip> </BadgeTooltip>
) )
} }

View File

@ -1,4 +1,4 @@
import QRCode from 'qrcode.react' import { QRCodeSVG } from 'qrcode.react'
import { CopyInput, InputSkeleton } from './form' import { CopyInput, InputSkeleton } from './form'
import InvoiceStatus from './invoice-status' import InvoiceStatus from './invoice-status'
import { useEffect } from 'react' import { useEffect } from 'react'
@ -25,8 +25,15 @@ export default function Qr ({ asIs, value, useWallet: automated, statusVariant,
return ( return (
<> <>
<a className='d-block p-3 mx-auto' style={{ background: 'white', maxWidth: '300px' }} href={qrValue}> <a className='d-block p-3 mx-auto' style={{ background: 'white', maxWidth: '300px' }} href={qrValue}>
<QRCode <QRCodeSVG
className='h-auto mw-100' value={qrValue} renderAs='svg' size={300} className='h-auto mw-100' value={qrValue} size={300} imageSettings={{
src: 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 256 256\'%3E%3Cpath fill-rule=\'evenodd\' d=\'m46.7 96.4 37.858 53.837-71.787 62.934L117.5 155.4l-40.075-52.854 49.412-59.492Zm156.35 41.546-49.416-58.509-34.909 116.771 44.25-67.358 58.509 59.25L241.4 47.725Z\'/%3E%3C/svg%3E',
x: undefined,
y: undefined,
height: 60,
width: 60,
excavate: true
}}
/> />
</a> </a>
{description && <div className='mt-1 text-center text-muted'>{description}</div>} {description && <div className='mt-1 text-center text-muted'>{description}</div>}

View File

@ -151,7 +151,7 @@ export const ServiceWorkerProvider = ({ children }) => {
const channel = new MessageChannel() const channel = new MessageChannel()
navigator?.serviceWorker?.controller?.postMessage({ action: ACTION_PORT }, [channel.port2]) navigator?.serviceWorker?.controller?.postMessage({ action: ACTION_PORT }, [channel.port2])
channel.port1.onmessage = (event) => { channel.port1.onmessage = (event) => {
if (event.data.action === RESUBSCRIBE) { if (event.data.action === RESUBSCRIBE && permission.notification === 'granted') {
return subscribeToPushNotifications() return subscribeToPushNotifications()
} }
} }
@ -161,7 +161,7 @@ export const ServiceWorkerProvider = ({ children }) => {
navigator?.serviceWorker?.controller?.postMessage?.({ action: SYNC_SUBSCRIPTION }) navigator?.serviceWorker?.controller?.postMessage?.({ action: SYNC_SUBSCRIPTION })
logger.info('sent SYNC_SUBSCRIPTION to service worker') logger.info('sent SYNC_SUBSCRIPTION to service worker')
navigator?.serviceWorker?.controller?.postMessage?.({ action: STORE_OS, os: detectOS() }) navigator?.serviceWorker?.controller?.postMessage?.({ action: STORE_OS, os: detectOS() })
}, [registration]) }, [registration, permission.notification])
const contextValue = useMemo(() => ({ const contextValue = useMemo(() => ({
registration, registration,

View File

@ -33,7 +33,7 @@ const rehypeSNStyled = () => rehypeSN({
}] }]
}) })
const remarkPlugins = [gfm, remarkMath] const remarkPlugins = [gfm, [remarkMath, { singleDollarTextMath: false }]]
const rehypePlugins = [rehypeSNStyled, rehypeMathjax] const rehypePlugins = [rehypeSNStyled, rehypeMathjax]
export function SearchText ({ text }) { export function SearchText ({ text }) {

View File

@ -10,7 +10,7 @@ import { gql, useApolloClient, useMutation } from '@apollo/client'
import styles from './user-header.module.css' import styles from './user-header.module.css'
import { useMe } from './me' import { useMe } from './me'
import { NAME_MUTATION } from '@/fragments/users' import { NAME_MUTATION } from '@/fragments/users'
import QRCode from 'qrcode.react' import { QRCodeSVG } from 'qrcode.react'
import LightningIcon from '@/svgs/bolt.svg' import LightningIcon from '@/svgs/bolt.svg'
import { encodeLNUrl } from '@/lib/lnurl' import { encodeLNUrl } from '@/lib/lnurl'
import Avatar from './avatar' import Avatar from './avatar'
@ -268,7 +268,7 @@ function HeaderHeader ({ user }) {
showModal(({ onClose }) => ( showModal(({ onClose }) => (
<> <>
<a className='d-flex m-auto p-3' style={{ background: 'white', maxWidth: 'fit-content' }} href={`lightning:${lnurlp}`}> <a className='d-flex m-auto p-3' style={{ background: 'white', maxWidth: 'fit-content' }} href={`lightning:${lnurlp}`}>
<QRCode className='d-flex m-auto' value={lnurlp} renderAs='svg' size={300} /> <QRCodeSVG className='d-flex m-auto' value={lnurlp} size={300} />
</a> </a>
<div className='text-center fw-bold text-muted mt-3'>click or scan</div> <div className='text-center fw-bold text-muted mt-3'>click or scan</div>
</> </>

View File

@ -26,6 +26,10 @@ class LRUCache {
return value return value
} }
delete (key) {
this.cache.delete(key)
}
set (key, value) { set (key, value) {
if (this.cache.has(key)) this.cache.delete(key) if (this.cache.has(key)) this.cache.delete(key)
else if (this.cache.size >= this.maxSize) { else if (this.cache.size >= this.maxSize) {

6822
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,98 +16,98 @@
"@apollo/client": "^3.11.8", "@apollo/client": "^3.11.8",
"@apollo/server": "^4.11.0", "@apollo/server": "^4.11.0",
"@as-integrations/next": "^3.1.0", "@as-integrations/next": "^3.1.0",
"@auth/prisma-adapter": "^1.0.3", "@auth/prisma-adapter": "^2.7.0",
"@graphql-tools/schema": "^10.0.0", "@graphql-tools/schema": "^10.0.6",
"@lightninglabs/lnc-web": "^0.3.2-alpha", "@lightninglabs/lnc-web": "^0.3.2-alpha",
"@noble/curves": "^1.2.0", "@noble/curves": "^1.6.0",
"@opensearch-project/opensearch": "^2.4.0", "@opensearch-project/opensearch": "^2.12.0",
"@prisma/client": "^5.17.0", "@prisma/client": "^5.20.0",
"@slack/web-api": "^6.9.0", "@slack/web-api": "^7.6.0",
"@svgr/webpack": "^8.1.0", "@svgr/webpack": "^8.1.0",
"@yudiel/react-qr-scanner": "^1.1.10", "@yudiel/react-qr-scanner": "^2.0.8",
"acorn": "^8.10.0", "acorn": "^8.12.1",
"ajv": "^8.12.0", "ajv": "^8.17.1",
"async-mutex": "^0.5.0", "async-mutex": "^0.5.0",
"async-retry": "^1.3.1", "async-retry": "^1.3.3",
"aws-sdk": "^2.1473.0", "aws-sdk": "^2.1691.0",
"bech32": "^2.0.0", "bech32": "^2.0.0",
"bolt11": "^1.4.1", "bolt11": "^1.4.1",
"bootstrap": "^5.3.2", "bootstrap": "^5.3.3",
"canonical-json": "0.0.4", "canonical-json": "0.0.4",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"clipboard-copy": "^4.0.1", "clipboard-copy": "^4.0.1",
"cookie": "^0.6.0", "cookie": "^1.0.1",
"cross-fetch": "^4.0.0", "cross-fetch": "^4.0.0",
"csv-parser": "^3.0.0", "csv-parser": "^3.0.0",
"domino": "^2.1.6", "domino": "^2.1.6",
"formik": "^2.4.5", "formik": "^2.4.6",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"google-protobuf": "^3.21.2", "google-protobuf": "^3.21.4",
"graphql": "^16.9.0", "graphql": "^16.9.0",
"graphql-scalar": "^0.1.0", "graphql-scalar": "^0.1.0",
"graphql-tag": "^2.12.6", "graphql-tag": "^2.12.6",
"graphql-type-json": "^0.3.2", "graphql-type-json": "^0.3.2",
"isomorphic-ws": "^5.0.0", "isomorphic-ws": "^5.0.0",
"ln-service": "^57.1.3", "ln-service": "^57.22.0",
"macaroon": "^3.0.4", "macaroon": "^3.0.4",
"mathjs": "^11.11.2", "mathjs": "^13.2.0",
"mdast-util-find-and-replace": "^3.0.1", "mdast-util-find-and-replace": "^3.0.1",
"mdast-util-from-markdown": "^2.0.0", "mdast-util-from-markdown": "^2.0.1",
"mdast-util-gfm": "^3.0.0", "mdast-util-gfm": "^3.0.0",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"micromark-extension-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0",
"next": "^13.5.7", "next": "^14.2.15",
"next-auth": "^4.23.2", "next-auth": "^4.24.8",
"next-plausible": "^3.12.2", "next-plausible": "^3.12.2",
"next-seo": "^6.1.0", "next-seo": "^6.6.0",
"node-s3-url-encode": "^0.0.4", "node-s3-url-encode": "^0.0.4",
"nodemailer": "^6.9.6", "nodemailer": "^6.9.15",
"nostr": "^0.2.8", "nostr": "^0.2.8",
"nostr-tools": "^2.7.2", "nostr-tools": "^2.8.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"opentimestamps": "^0.4.9", "opentimestamps": "^0.4.9",
"page-metadata-parser": "^1.1.4", "page-metadata-parser": "^1.1.4",
"pg-boss": "^9.0.3", "pg-boss": "^9.0.3",
"piexifjs": "^1.0.6", "piexifjs": "^1.0.6",
"prisma": "^5.17.0", "prisma": "^5.20.0",
"qrcode.react": "^3.1.0", "qrcode.react": "^4.0.1",
"react": "^18.2.0", "react": "^18.3.1",
"react-avatar-editor": "^13.0.0", "react-avatar-editor": "^13.0.2",
"react-bootstrap": "^2.9.0", "react-bootstrap": "^2.10.5",
"react-countdown": "^2.3.5", "react-countdown": "^2.3.6",
"react-datepicker": "^4.20.0", "react-datepicker": "^7.4.0",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-ios-pwa-prompt": "^1.8.4", "react-ios-pwa-prompt": "^1.8.4",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
"react-string-replace": "^1.1.1", "react-string-replace": "^1.1.1",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"react-textarea-autosize": "^8.5.3", "react-textarea-autosize": "^8.5.4",
"react-twitter-embed": "^4.0.4", "react-twitter-embed": "^4.0.4",
"react-youtube": "^10.1.0", "react-youtube": "^10.1.0",
"recharts": "^2.9.0", "recharts": "^2.13.0",
"rehype-mathjax": "^6.0.0", "rehype-mathjax": "^6.0.0",
"remark-gfm": "^4.0.0", "remark-gfm": "^4.0.0",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"remove-markdown": "^0.5.0", "remove-markdown": "^0.5.5",
"sass": "^1.69.3", "sass": "^1.79.5",
"serviceworker-storage": "^0.1.0", "serviceworker-storage": "^0.1.0",
"textarea-caret": "^3.1.0", "textarea-caret": "^3.1.0",
"tldts": "^6.0.16", "tldts": "^6.1.51",
"tsx": "^3.13.0", "tsx": "^4.19.1",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"unzipper": "^0.10.14", "unzipper": "^0.12.3",
"url-unshort": "^6.1.0", "url-unshort": "^6.1.0",
"web-push": "^3.6.6", "web-push": "^3.6.7",
"webln": "^0.3.2", "webln": "^0.3.2",
"webpack": "^5.89.0", "webpack": "^5.95.0",
"workbox-navigation-preload": "^7.0.0", "workbox-navigation-preload": "^7.1.0",
"workbox-precaching": "^7.0.0", "workbox-precaching": "^7.1.0",
"workbox-recipes": "^7.0.0", "workbox-recipes": "^7.1.0",
"workbox-routing": "^7.0.0", "workbox-routing": "^7.1.0",
"workbox-strategies": "^7.0.0", "workbox-strategies": "^7.1.0",
"workbox-webpack-plugin": "^7.0.0", "workbox-webpack-plugin": "^7.1.0",
"workbox-window": "^7.0.0", "workbox-window": "^7.1.0",
"yup": "^1.3.2" "yup": "^1.4.0"
}, },
"engines": { "engines": {
"node": "18.20.4" "node": "18.20.4"
@ -121,10 +121,10 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@next/eslint-plugin-next": "^13.5.4", "@next/eslint-plugin-next": "^14.2.15",
"eslint": "^8.51.0", "eslint": "^9.12.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"standard": "^17.1.0" "standard": "^17.1.2"
}, },
"jest": { "jest": {
"moduleNameMapper": { "moduleNameMapper": {

View File

@ -13,7 +13,7 @@ import { datePivot } from '@/lib/time'
import { schnorr } from '@noble/curves/secp256k1' import { schnorr } from '@noble/curves/secp256k1'
import { notifyReferral } from '@/lib/webPush' import { notifyReferral } from '@/lib/webPush'
import { hashEmail } from '@/lib/crypto' import { hashEmail } from '@/lib/crypto'
import cookie from 'cookie' import * as cookie from 'cookie'
/** /**
* Stores userIds in user table * Stores userIds in user table

View File

@ -1,4 +1,4 @@
import cookie from 'cookie' import * as cookie from 'cookie'
import { datePivot } from '../../lib/time' import { datePivot } from '../../lib/time'
/** /**

View File

@ -370,7 +370,7 @@ export default function Settings ({ ssrData }) {
groupClassName='mb-0' groupClassName='mb-0'
/> />
<Checkbox <Checkbox
label={<>hide my cowboy hat</>} label={<>hide my cowboy essentials (e.g. cowboy hat)</>}
name='hideCowboyHat' name='hideCowboyHat'
groupClassName='mb-0' groupClassName='mb-0'
/> />

View File

@ -22,7 +22,7 @@ import HiddenWalletSummary from '@/components/hidden-wallet-summary'
import AccordianItem from '@/components/accordian-item' import AccordianItem from '@/components/accordian-item'
import { lnAddrOptions } from '@/lib/lnurl' import { lnAddrOptions } from '@/lib/lnurl'
import useDebounceCallback from '@/components/use-debounce-callback' import useDebounceCallback from '@/components/use-debounce-callback'
import { QrScanner } from '@yudiel/react-qr-scanner' import { Scanner } from '@yudiel/react-qr-scanner'
import CameraIcon from '@/svgs/camera-line.svg' import CameraIcon from '@/svgs/camera-line.svg'
import { useShowModal } from '@/components/modal' import { useShowModal } from '@/components/modal'
import { useField } from 'formik' import { useField } from 'formik'
@ -282,17 +282,24 @@ function InvoiceScanner ({ fieldName }) {
onClick={() => { onClick={() => {
showModal(onClose => { showModal(onClose => {
return ( return (
<QrScanner <Scanner
onDecode={(result) => { formats={['qr_code']}
onScan={([{ rawValue: result }]) => {
result = result.toLowerCase()
if (result.split('lightning=')[1]) { if (result.split('lightning=')[1]) {
helpers.setValue(result.split('lightning=')[1].split(/[&?]/)[0].toLowerCase()) helpers.setValue(result.split('lightning=')[1].split(/[&?]/)[0])
} else if (decode(result.replace(/^lightning:/, ''))) { } else if (decode(result.replace(/^lightning:/, ''))) {
helpers.setValue(result.replace(/^lightning:/, '').toLowerCase()) helpers.setValue(result.replace(/^lightning:/, ''))
} else { } else {
throw new Error('Not a proper lightning payment request') throw new Error('Not a proper lightning payment request')
} }
onClose() onClose()
}} }}
styles={{
video: {
aspectRatio: '1 / 1'
}
}}
onError={(error) => { onError={(error) => {
if (error instanceof DOMException) { if (error instanceof DOMException) {
console.log(error) console.log(error)