diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index d7c4f8be..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: Bug report
-about: Report a problem
-title: ''
-labels: bug
-assignees: ''
-
----
-
-*Note: this template is meant to help you report the bug so that we can fix it faster, ie not all of these sections are required*
-
-**Description**
-A clear and concise description of what the bug is.
-
-**Steps to Reproduce**
-A clear and concise way we might be able to reproduce the bug.
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Logs**
-If applicable, add your browsers console logs.
-
-**Environment:**
-If you only experience the issue on certain devices or browsers, provide that info.
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
-
-**Additional context**
-Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000..d05bbe6f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,65 @@
+name: 🐞 Bug report
+description: Create a bug report to help us fix it
+title: "bug report"
+labels: [bug]
+body:
+ - type: checkboxes
+ attributes:
+ label: Is there an existing issue for this?
+ description: Please search to see if an issue already exists for the bug you encountered.
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the bug
+ description: A clear and concise description of what the bug is. Include images if relevant.
+ placeholder: I accidentally deleted the internet. Here's my story ...
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Screenshots
+ description: |
+ Add screenshots to help explain your problem. You can also add a video here.
+
+ Tip: You can attach images or video files by clicking this area to highlight it and then dragging files in.
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Steps To Reproduce
+ description: Steps to reproduce the bug.
+ placeholder: |
+ 1. Go to '...'
+ 2. Click on '...'
+ 3. Scroll to '...'
+ 4. See error
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Expected behavior
+ description: A clear and concise description of what you expected to happen
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Logs
+ description: If applicable, add your browser's console logs here
+ - type: textarea
+ attributes:
+ label: Device information
+ placeholder: |
+ - OS: [e.g. Windows]
+ - Browser: [e.g. chrome, safari, firefox]
+ - Browser Version: [e.g. 22]
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: |
+ Do you have links to discussions about this on SN or other references?
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..075e285b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: true
+contact_links:
+ - name: Questions
+ url: https://stacker.news/~meta
+ about: If you simply have a question, you can ask it in ~meta or the saloon.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index ba14c610..00000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest a feature
-title: ''
-labels: feature
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 00000000..0c4c5a53
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,32 @@
+name: ✨ Feature request
+description: Request a feature you'd like to see in SN!
+title: "feature request"
+labels: [feature]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ We're always looking for suggestions on how we could improve SN!
+ - type: textarea
+ attributes:
+ label: Describe the problem you're trying to solve
+ description: |
+ Is your feature request related to a problem? Add a clear and concise description of what the problem is.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe the solution you'd like
+ description: A clear and concise description of what you want to happen.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Describe alternatives you've considered
+ description: |
+ A clear and concise description of any alternative solutions or features you have considered.
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: |
+ Add any other additional context or screenshots about the feature request here.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 309e2e77..e46d30f1 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,45 +1,22 @@
## Description
-
+_A clear and concise description of what you changed and why._
## Screenshots
-
-
## Additional Context
-
+_Was anything unclear during your work on this PR? Anything we should definitely take a closer look at?_
## Checklist
**Are your changes backwards compatible? Please answer below:**
-
-
**On a scale of 1-10 how well and how have you QA'd this change and any features it might affect? Please answer below:**
-
**For frontend changes: Tested on mobile? Please answer below:**
-
**Did you introduce any new environment variables? If so, call them out explicitly here:**
-
-
diff --git a/api/paidAction/index.js b/api/paidAction/index.js
index 424198be..fcbfb4e3 100644
--- a/api/paidAction/index.js
+++ b/api/paidAction/index.js
@@ -258,8 +258,10 @@ export async function createLightningInvoice (actionType, args, context) {
expiry: INVOICE_EXPIRE_SECS
}, { models })
+ // the sender (me) decides if the wrapped invoice has a description
+ // whereas the recipient decides if their invoice has a description
const { invoice: wrappedInvoice, maxFee } = await wrapInvoice(
- bolt11, { msats: cost, description }, { lnd })
+ bolt11, { msats: cost, description }, { me, lnd })
return {
bolt11,
diff --git a/components/comment.js b/components/comment.js
index 176ab6f1..62e455f3 100644
--- a/components/comment.js
+++ b/components/comment.js
@@ -180,7 +180,8 @@ export default function Comment ({
}
>
}
- onEdit={e => { setEdit(!edit) }}
+ edit={edit}
+ toggleEdit={e => { setEdit(!edit) }}
editText={edit ? 'cancel' : 'edit'}
/>}
diff --git a/components/item-info.js b/components/item-info.js
index ba0c3732..921d57f5 100644
--- a/components/item-info.js
+++ b/components/item-info.js
@@ -30,7 +30,7 @@ import classNames from 'classnames'
export default function ItemInfo ({
item, full, commentsText = 'comments',
- commentTextSingular = 'comment', className, embellishUser, extraInfo, onEdit, editText,
+ commentTextSingular = 'comment', className, embellishUser, extraInfo, edit, toggleEdit, editText,
onQuoteReply, extraBadges, nested, pinnable, showActionDropdown = true, showUser = true,
setDisableRetry, disableRetry
}) {
@@ -151,8 +151,8 @@ export default function ItemInfo ({
showActionDropdown &&
<>
@@ -311,7 +311,7 @@ function PaymentInfo ({ item, disableRetry, setDisableRetry }) {
)
}
-function EditInfo ({ item, canEdit, setCanEdit, onEdit, editText, editThreshold }) {
+function EditInfo ({ item, edit, canEdit, setCanEdit, toggleEdit, editText, editThreshold }) {
const router = useRouter()
if (canEdit) {
@@ -320,7 +320,7 @@ function EditInfo ({ item, canEdit, setCanEdit, onEdit, editText, editThreshold
\
onEdit ? onEdit() : router.push(`/items/${item.id}/edit`)}
+ onClick={() => toggleEdit ? toggleEdit() : router.push(`/items/${item.id}/edit`)}
>
{editText || 'edit'}
{(!item.invoice?.actionState || item.invoice?.actionState === 'PAID')
@@ -334,5 +334,21 @@ function EditInfo ({ item, canEdit, setCanEdit, onEdit, editText, editThreshold
)
}
+ if (edit && !canEdit) {
+ // if we're still editing after timer ran out
+ return (
+ <>
+ \
+ toggleEdit ? toggleEdit() : router.push(`/items/${item.id}`)}
+ >
+ cancel
+ 00:00
+
+ >
+ )
+ }
+
return null
}
diff --git a/components/text.js b/components/text.js
index fe70f0a2..43b9a387 100644
--- a/components/text.js
+++ b/components/text.js
@@ -17,6 +17,7 @@ import ItemPopover from './item-popover'
import classNames from 'classnames'
import { CarouselProvider, useCarousel } from './carousel'
import rehypeSN from '@/lib/rehype-sn'
+import remarkUnicode from '@/lib/remark-unicode'
import Embed from './embed'
import remarkMath from 'remark-math'
import rehypeMathjax from 'rehype-mathjax'
@@ -33,7 +34,7 @@ const rehypeSNStyled = () => rehypeSN({
}]
})
-const remarkPlugins = [gfm, [remarkMath, { singleDollarTextMath: false }]]
+const remarkPlugins = [gfm, remarkUnicode, [remarkMath, { singleDollarTextMath: false }]]
const rehypePlugins = [rehypeSNStyled, rehypeMathjax]
export function SearchText ({ text }) {
diff --git a/components/wallet-card.js b/components/wallet-card.js
index aedd792c..e1ae443c 100644
--- a/components/wallet-card.js
+++ b/components/wallet-card.js
@@ -51,10 +51,18 @@ export default function WalletCard ({ wallet, draggable, onDragStart, onDragEnte
{title}
{badges?.map(
- badge =>
-
- {badge}
- )}
+ badge => {
+ let style = ''
+ switch (badge) {
+ case 'receive': style = styles.receive; break
+ case 'send': style = styles.send; break
+ }
+ return (
+
+ {badge}
+
+ )
+ })}
diff --git a/lib/remark-unicode.js b/lib/remark-unicode.js
new file mode 100644
index 00000000..19c830ad
--- /dev/null
+++ b/lib/remark-unicode.js
@@ -0,0 +1,31 @@
+import { visit } from 'unist-util-visit'
+
+export default function remarkFilterUnicode () {
+ return (tree) => {
+ try {
+ visit(tree, 'paragraph', (node) => {
+ node.children = node.children.map(child => {
+ if (child.type !== 'inlineMath') return child
+
+ // if inline math contains currency symbols, rehypeMathjax will throw
+ // see https://github.com/stackernews/stacker.news/issues/1525
+ // and https://github.com/stackernews/stacker.news/pull/1526
+
+ let { hChildren } = child.data
+ hChildren = hChildren.map(child2 => {
+ return { ...child2, value: filterUnicode(child2.value) }
+ })
+ child.data.hChildren = hChildren
+
+ return { ...child, value: filterUnicode(child.value) }
+ })
+ })
+ } catch (err) {
+ console.error(err)
+ }
+ }
+}
+
+function filterUnicode (text) {
+ return text.replace(/\p{Sc}/u, '')
+}
diff --git a/pages/invites/index.js b/pages/invites/index.js
index b00c03d7..37c71b13 100644
--- a/pages/invites/index.js
+++ b/pages/invites/index.js
@@ -27,6 +27,7 @@ function InviteForm () {
fields: {
invites (existingInviteRefs = []) {
const newInviteRef = cache.writeFragment({
+ fragmentName: 'InviteFields',
data: createInvite,
fragment: INVITE_FIELDS
})
diff --git a/prisma/migrations/20241101151907_fix_territory_revenue/migration.sql b/prisma/migrations/20241101151907_fix_territory_revenue/migration.sql
new file mode 100644
index 00000000..0a92b67f
--- /dev/null
+++ b/prisma/migrations/20241101151907_fix_territory_revenue/migration.sql
@@ -0,0 +1,28 @@
+-- fix revenue for users who have multiple revenue entries for the same day
+WITH revenue_days AS (
+ SELECT coalesce(sum(msats), 0) as revenue_msats, "userId", created_at
+ FROM "SubAct"
+ WHERE type = 'REVENUE'
+ GROUP BY "userId", created_at
+ HAVING COUNT(*) > 1
+),
+revenue_total AS (
+ SELECT coalesce(sum(revenue_msats), 0) as revenue_msats, "userId"
+ FROM revenue_days
+ GROUP BY "userId"
+)
+UPDATE users SET msats = users.msats + revenue_total.revenue_msats
+FROM revenue_total
+WHERE users.id = revenue_total."userId";
+
+-- fix stacked msats for users who have territory revenue
+-- prior to this, we were not updating stacked msats for territory revenue
+WITH territory_revenue AS (
+ SELECT coalesce(sum(msats), 0) as revenue_msats, "userId"
+ FROM "SubAct"
+ WHERE type = 'REVENUE'
+ GROUP BY "userId"
+)
+UPDATE users SET "stackedMsats" = users."stackedMsats" + territory_revenue.revenue_msats
+FROM territory_revenue
+WHERE users.id = territory_revenue."userId";
diff --git a/styles/wallet.module.css b/styles/wallet.module.css
index e4e8744a..133734d4 100644
--- a/styles/wallet.module.css
+++ b/styles/wallet.module.css
@@ -40,6 +40,14 @@
margin-right: 0.2rem;
}
+.receive {
+ color: #20c997 !important;
+}
+
+.send {
+ color: var(--bs-primary) !important;
+}
+
.attach {
color: var(--bs-body-color) !important;
text-align: center;
diff --git a/wallets/blink/index.js b/wallets/blink/index.js
index 6cbc3ff8..dc93d042 100644
--- a/wallets/blink/index.js
+++ b/wallets/blink/index.js
@@ -28,7 +28,7 @@ export const fields = [
export const card = {
title: 'Blink',
subtitle: 'use [Blink](https://blink.sv/) for payments',
- badges: ['send only']
+ badges: ['send']
}
export const fieldValidation = blinkSchema
diff --git a/wallets/cln/index.js b/wallets/cln/index.js
index 644b7748..31e05606 100644
--- a/wallets/cln/index.js
+++ b/wallets/cln/index.js
@@ -36,7 +36,7 @@ export const fields = [
export const card = {
title: 'CLN',
subtitle: 'autowithdraw to your Core Lightning node via [CLNRest](https://docs.corelightning.org/docs/rest)',
- badges: ['receive only']
+ badges: ['receive']
}
export const fieldValidation = CLNAutowithdrawSchema
diff --git a/wallets/lightning-address/index.js b/wallets/lightning-address/index.js
index ff502a3a..9a881d03 100644
--- a/wallets/lightning-address/index.js
+++ b/wallets/lightning-address/index.js
@@ -15,7 +15,7 @@ export const fields = [
export const card = {
title: 'lightning address',
subtitle: 'autowithdraw to a lightning address',
- badges: ['receive only']
+ badges: ['receive']
}
export const fieldValidation = lnAddrAutowithdrawSchema
diff --git a/wallets/lnbits/index.js b/wallets/lnbits/index.js
index 3473f47e..a4425911 100644
--- a/wallets/lnbits/index.js
+++ b/wallets/lnbits/index.js
@@ -29,7 +29,7 @@ export const fields = [
export const card = {
title: 'LNbits',
subtitle: 'use [LNbits](https://lnbits.com/) for payments',
- badges: ['send & receive']
+ badges: ['send', 'receive']
}
export const fieldValidation = lnbitsSchema
diff --git a/wallets/lnc/index.js b/wallets/lnc/index.js
index e349b6dd..b86153da 100644
--- a/wallets/lnc/index.js
+++ b/wallets/lnc/index.js
@@ -33,7 +33,7 @@ export const fields = [
export const card = {
title: 'LNC',
subtitle: 'use Lightning Node Connect for LND payments',
- badges: ['send only', 'budgetable']
+ badges: ['send', 'budgetable']
}
export const fieldValidation = lncSchema
diff --git a/wallets/lnd/index.js b/wallets/lnd/index.js
index c884b909..21123cb5 100644
--- a/wallets/lnd/index.js
+++ b/wallets/lnd/index.js
@@ -37,7 +37,7 @@ export const fields = [
export const card = {
title: 'LND',
subtitle: 'autowithdraw to your Lightning Labs node',
- badges: ['receive only']
+ badges: ['receive']
}
export const fieldValidation = LNDAutowithdrawSchema
diff --git a/wallets/nwc/index.js b/wallets/nwc/index.js
index fe443968..cd125769 100644
--- a/wallets/nwc/index.js
+++ b/wallets/nwc/index.js
@@ -27,7 +27,7 @@ export const fields = [
export const card = {
title: 'NWC',
subtitle: 'use Nostr Wallet Connect for payments',
- badges: ['send & receive', 'budgetable']
+ badges: ['send', 'receive', 'budgetable']
}
export const fieldValidation = nwcSchema
diff --git a/wallets/phoenixd/index.js b/wallets/phoenixd/index.js
index 51625937..5a24e304 100644
--- a/wallets/phoenixd/index.js
+++ b/wallets/phoenixd/index.js
@@ -33,7 +33,7 @@ export const fields = [
export const card = {
title: 'phoenixd',
subtitle: 'use [phoenixd](https://phoenix.acinq.co/server) for payments',
- badges: ['send & receive']
+ badges: ['send', 'receive']
}
// phoenixd::TODO
diff --git a/wallets/webln/index.js b/wallets/webln/index.js
index 6bfb26d5..75ca3dd8 100644
--- a/wallets/webln/index.js
+++ b/wallets/webln/index.js
@@ -20,7 +20,7 @@ export const fieldValidation = ({ enabled }) => {
export const card = {
title: 'WebLN',
subtitle: 'use a [WebLN provider](https://www.webln.guide/ressources/webln-providers) for payments',
- badges: ['send only']
+ badges: ['send']
}
export default function WebLnProvider ({ children }) {
diff --git a/wallets/wrap.js b/wallets/wrap.js
index ae63a6ed..b470587b 100644
--- a/wallets/wrap.js
+++ b/wallets/wrap.js
@@ -22,7 +22,7 @@ const ZAP_SYBIL_FEE_MULT = 10 / 7 // the fee for the zap sybil service
maxFee: number
}
*/
-export default async function wrapInvoice (bolt11, { msats, description, descriptionHash }, { lnd }) {
+export default async function wrapInvoice (bolt11, { msats, description, descriptionHash }, { me, lnd }) {
try {
console.group('wrapInvoice', description)
@@ -112,6 +112,11 @@ export default async function wrapInvoice (bolt11, { msats, description, descrip
wrapped.description = inv.description
}
+ if (me?.hideInvoiceDesc) {
+ wrapped.description = undefined
+ wrapped.description_hash = undefined
+ }
+
// validate the expiration
if (new Date(inv.expires_at) < new Date(Date.now() + INCOMING_EXPIRATION_BUFFER_MSECS)) {
throw new Error('Invoice expiration is too soon')
diff --git a/worker/territory.js b/worker/territory.js
index 21bb87b7..d7a7f479 100644
--- a/worker/territory.js
+++ b/worker/territory.js
@@ -72,10 +72,17 @@ export async function territoryRevenue ({ models }) {
FROM revenue
WHERE revenue > 1000
RETURNING *
+ ),
+ "SubActResultTotal" AS (
+ SELECT coalesce(sum(msats), 0) as total_msats, "userId"
+ FROM "SubActResult"
+ GROUP BY "userId"
)
- UPDATE users SET msats = users.msats + "SubActResult".msats
- FROM "SubActResult"
- WHERE users.id = "SubActResult"."userId"`,
+ UPDATE users
+ SET msats = users.msats + "SubActResultTotal".total_msats,
+ "stackedMsats" = users."stackedMsats" + "SubActResultTotal".total_msats
+ FROM "SubActResultTotal"
+ WHERE users.id = "SubActResultTotal"."userId"`,
{ models }
)
}