Skip to content

Commit a33c0d6

Browse files
authored
Merge branch 'master' into subscribe_unarchiver
2 parents 7bf2c3c + ca7726f commit a33c0d6

File tree

8 files changed

+52
-24
lines changed

8 files changed

+52
-24
lines changed

api/resolvers/item.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { verifyHmac } from './wallet'
2626

2727
function commentsOrderByClause (me, models, sort) {
2828
if (sort === 'recent') {
29-
return 'ORDER BY ("Item"."deletedAt" IS NULL) DESC, ("Item".cost > 0 OR "Item"."weightedVotes" - "Item"."weightedDownVotes" > 0) DESC, "Item".created_at DESC, "Item".id DESC'
29+
return 'ORDER BY ("Item"."deletedAt" IS NULL) DESC, ("Item".cost > 0 OR "Item"."weightedVotes" - "Item"."weightedDownVotes" > 0) DESC, COALESCE("Item"."invoicePaidAt", "Item".created_at) DESC, "Item".id DESC'
3030
}
3131

3232
if (me && sort === 'hot') {
@@ -412,10 +412,10 @@ export default {
412412
typeClause(type),
413413
muteClause(me)
414414
)}
415-
ORDER BY "Item".created_at DESC
415+
ORDER BY COALESCE("Item"."invoicePaidAt", "Item".created_at) DESC
416416
OFFSET $2
417417
LIMIT $3`,
418-
orderBy: 'ORDER BY "Item"."createdAt" DESC'
418+
orderBy: 'ORDER BY COALESCE("Item"."invoicePaidAt", "Item".created_at) DESC'
419419
}, decodedCursor.time, decodedCursor.offset, limit, ...subArr)
420420
break
421421
case 'top':
@@ -536,8 +536,8 @@ export default {
536536
LEFT JOIN "Sub" ON "Sub"."name" = "Item"."subName"
537537
${joinZapRankPersonalView(me, models)}
538538
${whereClause(
539-
// in "home" (sub undefined), we want to show pinned items (but without the pin icon)
540-
sub ? '"Item"."pinId" IS NULL' : '',
539+
// in home (sub undefined), filter out global pinned items since we inject them later
540+
sub ? '"Item"."pinId" IS NULL' : 'NOT ("Item"."pinId" IS NOT NULL AND "Item"."subName" IS NULL)',
541541
'"Item"."deletedAt" IS NULL',
542542
'"Item"."parentId" IS NULL',
543543
'"Item".outlawed = false',
@@ -565,8 +565,8 @@ export default {
565565
${whereClause(
566566
subClause(sub, 3, 'Item', me, showNsfw),
567567
muteClause(me),
568-
// in "home" (sub undefined), we want to show pinned items (but without the pin icon)
569-
sub ? '"Item"."pinId" IS NULL' : '',
568+
// in home (sub undefined), filter out global pinned items since we inject them later
569+
sub ? '"Item"."pinId" IS NULL' : 'NOT ("Item"."pinId" IS NOT NULL AND "Item"."subName" IS NULL)',
570570
'"Item"."deletedAt" IS NULL',
571571
'"Item"."parentId" IS NULL',
572572
'"Item".bio = false',

api/typeDefs/item.js

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export default gql`
107107
id: ID!
108108
createdAt: Date!
109109
updatedAt: Date!
110+
invoicePaidAt: Date
110111
deletedAt: Date
111112
deleteScheduledAt: Date
112113
reminderScheduledAt: Date

components/item-info.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ export default function ItemInfo ({
135135
{embellishUser}
136136
</Link>}
137137
<span> </span>
138-
<Link href={`/items/${item.id}`} title={item.createdAt} className='text-reset' suppressHydrationWarning>
139-
{timeSince(new Date(item.createdAt))}
138+
<Link href={`/items/${item.id}`} title={item.invoicePaidAt || item.createdAt} className='text-reset' suppressHydrationWarning>
139+
{timeSince(new Date(item.invoicePaidAt || item.createdAt))}
140140
</Link>
141141
{item.prior &&
142142
<>
@@ -250,6 +250,11 @@ function InfoDropdownItem ({ item }) {
250250
<div>{item.id}</div>
251251
<div>created at</div>
252252
<div>{item.createdAt}</div>
253+
{item.invoicePaidAt &&
254+
<>
255+
<div>paid at</div>
256+
<div>{item.invoicePaidAt}</div>
257+
</>}
253258
<div>cost</div>
254259
<div>{item.cost}</div>
255260
<div>stacked</div>

fragments/comments.js

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const COMMENT_FIELDS = gql`
1818
position
1919
parentId
2020
createdAt
21+
invoicePaidAt
2122
deletedAt
2223
text
2324
user {

fragments/items.js

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const ITEM_FIELDS = gql`
1818
id
1919
parentId
2020
createdAt
21+
invoicePaidAt
2122
deletedAt
2223
title
2324
url

lib/webPush.js

+31-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { COMMENT_DEPTH_LIMIT, FOUND_BLURBS, LOST_BLURBS } from './constants'
44
import { msatsToSats, numWithUnits } from './format'
55
import models from '@/api/models'
66
import { isMuted } from '@/lib/user'
7+
import { Prisma } from '@prisma/client'
78

89
const webPushEnabled = process.env.NODE_ENV === 'production' ||
910
(process.env.VAPID_MAILTO && process.env.NEXT_PUBLIC_VAPID_PUBKEY && process.env.VAPID_PRIVKEY)
@@ -123,21 +124,36 @@ export async function replyToSubscription (subscriptionId, notification) {
123124
export const notifyUserSubscribers = async ({ models, item }) => {
124125
try {
125126
const isPost = !!item.title
126-
const userSubsExcludingMutes = await models.$queryRawUnsafe(`
127-
SELECT "UserSubscription"."followerId", "UserSubscription"."followeeId", users.name as "followeeName"
128-
FROM "UserSubscription"
129-
INNER JOIN users ON users.id = "UserSubscription"."followeeId"
130-
WHERE "followeeId" = $1 AND ${isPost ? '"postsSubscribedAt"' : '"commentsSubscribedAt"'} IS NOT NULL
131-
AND NOT EXISTS (SELECT 1 FROM "Mute" WHERE "Mute"."muterId" = "UserSubscription"."followerId" AND "Mute"."mutedId" = $1)
132-
-- ignore subscription if user was already notified of item as a reply
133-
AND NOT EXISTS (
134-
SELECT 1 FROM "Reply"
135-
INNER JOIN users follower ON follower.id = "UserSubscription"."followerId"
136-
WHERE "Reply"."itemId" = $2
137-
AND "Reply"."ancestorUserId" = follower.id
138-
AND follower."noteAllDescendants"
139-
)
140-
`, Number(item.userId), Number(item.id))
127+
128+
const userSubsExcludingMutes = await models.$queryRaw`
129+
SELECT "UserSubscription"."followerId", "UserSubscription"."followeeId", users.name as "followeeName"
130+
FROM "UserSubscription"
131+
INNER JOIN users ON users.id = "UserSubscription"."followeeId"
132+
WHERE "followeeId" = ${Number(item.userId)}::INTEGER
133+
AND ${isPost ? Prisma.sql`"postsSubscribedAt"` : Prisma.sql`"commentsSubscribedAt"`} IS NOT NULL
134+
-- ignore muted users
135+
AND NOT EXISTS (
136+
SELECT 1
137+
FROM "Mute"
138+
WHERE "Mute"."muterId" = "UserSubscription"."followerId"
139+
AND "Mute"."mutedId" = ${Number(item.userId)}::INTEGER)
140+
-- ignore subscription if user was already notified of item as a reply
141+
AND NOT EXISTS (
142+
SELECT 1 FROM "Reply"
143+
INNER JOIN users follower ON follower.id = "UserSubscription"."followerId"
144+
WHERE "Reply"."itemId" = ${Number(item.id)}::INTEGER
145+
AND "Reply"."ancestorUserId" = follower.id
146+
AND follower."noteAllDescendants"
147+
)
148+
-- ignore subscription if user has posted to a territory the recipient is subscribed to
149+
${isPost
150+
? Prisma.sql`AND NOT EXISTS (
151+
SELECT 1
152+
FROM "SubSubscription"
153+
WHERE "SubSubscription"."userId" = "UserSubscription"."followerId"
154+
AND "SubSubscription"."subName" = ${item.subName}
155+
)`
156+
: Prisma.empty}`
141157
const subType = isPost ? 'POST' : 'COMMENT'
142158
const tag = `FOLLOW-${item.userId}-${subType}`
143159
await Promise.allSettled(userSubsExcludingMutes.map(({ followerId, followeeName }) => sendUserNotification(followerId, {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- CreateIndex
2+
CREATE INDEX "Item_invoicePaidAt_idx" ON "Item"("invoicePaidAt");
3+
CREATE INDEX "Item_paid_created_idx" ON "Item" (COALESCE("invoicePaidAt", created_at) DESC);

prisma/schema.prisma

+1
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ model Item {
598598
@@index([cost])
599599
@@index([url])
600600
@@index([boost])
601+
@@index([invoicePaidAt])
601602
}
602603

603604
// we use this to denormalize a user's aggregated interactions (zaps) with an item

0 commit comments

Comments
 (0)