feat: comment fee control (#1768)
* feat: comment fee control * update typeDefs for unarchiving territories * review: move functions to top level; consider saloon items * ux: cleaner post/reply cost section * hotfix: handle salon replies * bios don't have subs + simplify root query * move reply cost to accordian --------- Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com> Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
parent
ac321be3cd
commit
5c2aa979ea
@ -13,9 +13,33 @@ export const paymentMethods = [
|
||||
PAID_ACTION_PAYMENT_METHODS.PESSIMISTIC
|
||||
]
|
||||
|
||||
export const DEFAULT_ITEM_COST = 1000n
|
||||
|
||||
export async function getBaseCost ({ models, bio, parentId, subName }) {
|
||||
if (bio) return DEFAULT_ITEM_COST
|
||||
|
||||
if (parentId) {
|
||||
// the subname is stored in the root item of the thread
|
||||
const parent = await models.item.findFirst({
|
||||
where: { id: Number(parentId) },
|
||||
include: {
|
||||
root: { include: { sub: true } },
|
||||
sub: true
|
||||
}
|
||||
})
|
||||
|
||||
const root = parent.root ?? parent
|
||||
|
||||
if (!root.sub) return DEFAULT_ITEM_COST
|
||||
return satsToMsats(root.sub.replyCost)
|
||||
}
|
||||
|
||||
const sub = await models.sub.findUnique({ where: { name: subName } })
|
||||
return satsToMsats(sub.baseCost)
|
||||
}
|
||||
|
||||
export async function getCost ({ subName, parentId, uploadIds, boost = 0, bio }, { models, me }) {
|
||||
const sub = (parentId || bio) ? null : await models.sub.findUnique({ where: { name: subName } })
|
||||
const baseCost = sub ? satsToMsats(sub.baseCost) : 1000n
|
||||
const baseCost = await getBaseCost({ models, bio, parentId, subName })
|
||||
|
||||
// cost = baseCost * 10^num_items_in_10m * 100 (anon) or 1 (user) + upload fees + boost
|
||||
const [{ cost }] = await models.$queryRaw`
|
||||
|
@ -16,6 +16,7 @@ export default gql`
|
||||
|
||||
extend type Mutation {
|
||||
upsertSub(oldName: String, name: String!, desc: String, baseCost: Int!,
|
||||
replyCost: Int!,
|
||||
postTypes: [String!]!,
|
||||
billingType: String!, billingAutoRenew: Boolean!,
|
||||
moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
|
||||
@ -24,7 +25,7 @@ export default gql`
|
||||
toggleSubSubscription(name: String!): Boolean!
|
||||
transferTerritory(subName: String!, userName: String!): Sub
|
||||
unarchiveTerritory(name: String!, desc: String, baseCost: Int!,
|
||||
postTypes: [String!]!,
|
||||
replyCost: Int!, postTypes: [String!]!,
|
||||
billingType: String!, billingAutoRenew: Boolean!,
|
||||
moderated: Boolean!, nsfw: Boolean!): SubPaidAction!
|
||||
}
|
||||
@ -45,6 +46,7 @@ export default gql`
|
||||
billedLastAt: Date!
|
||||
billPaidUntil: Date
|
||||
baseCost: Int!
|
||||
replyCost: Int!
|
||||
status: String!
|
||||
moderated: Boolean!
|
||||
moderatedCount: Int!
|
||||
|
@ -161,7 +161,7 @@ export default forwardRef(function Reply ({
|
||||
{reply &&
|
||||
<div className={styles.reply}>
|
||||
<FeeButtonProvider
|
||||
baseLineItems={postCommentBaseLineItems({ baseCost: 1, comment: true, me: !!me })}
|
||||
baseLineItems={postCommentBaseLineItems({ baseCost: sub?.replyCost ?? 1, comment: true, me: !!me })}
|
||||
useRemoteLineItems={postCommentUseRemoteLineItems({ parentId: item.id, me: !!me })}
|
||||
>
|
||||
<Form
|
||||
|
@ -91,6 +91,7 @@ export default function TerritoryForm ({ sub }) {
|
||||
name: sub?.name || '',
|
||||
desc: sub?.desc || '',
|
||||
baseCost: sub?.baseCost || 10,
|
||||
replyCost: sub?.replyCost || 1,
|
||||
postTypes: sub?.postTypes || POST_TYPES,
|
||||
billingType: sub?.billingType || 'MONTHLY',
|
||||
billingAutoRenew: sub?.billingAutoRenew || false,
|
||||
@ -234,6 +235,13 @@ export default function TerritoryForm ({ sub }) {
|
||||
header={<div style={{ fontWeight: 'bold', fontSize: '92%' }}>options</div>}
|
||||
body={
|
||||
<>
|
||||
<Input
|
||||
label='reply cost'
|
||||
name='replyCost'
|
||||
type='number'
|
||||
required
|
||||
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
|
||||
/>
|
||||
<BootstrapForm.Label>moderation</BootstrapForm.Label>
|
||||
<Checkbox
|
||||
inline
|
||||
|
@ -57,10 +57,17 @@ export function TerritoryInfo ({ sub }) {
|
||||
<span> on </span>
|
||||
<span className='fw-bold'>{new Date(sub.createdAt).toDateString()}</span>
|
||||
</div>
|
||||
<div className='d-flex'>
|
||||
<div className='text-muted'>
|
||||
<span>post cost </span>
|
||||
<span className='fw-bold'>{numWithUnits(sub.baseCost)}</span>
|
||||
</div>
|
||||
<span className='px-1'> \ </span>
|
||||
<div className='text-muted'>
|
||||
<span>reply cost </span>
|
||||
<span className='fw-bold'>{numWithUnits(sub.replyCost)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<TerritoryBillingLine sub={sub} />
|
||||
</CardFooter>
|
||||
</>
|
||||
|
@ -35,6 +35,7 @@ export const ITEM_FIELDS = gql`
|
||||
meMuteSub
|
||||
meSubscription
|
||||
nsfw
|
||||
replyCost
|
||||
}
|
||||
otsHash
|
||||
position
|
||||
|
@ -264,10 +264,10 @@ export const UPDATE_COMMENT = gql`
|
||||
export const UPSERT_SUB = gql`
|
||||
${PAID_ACTION}
|
||||
mutation upsertSub($oldName: String, $name: String!, $desc: String, $baseCost: Int!,
|
||||
$postTypes: [String!]!, $billingType: String!,
|
||||
$replyCost: Int!, $postTypes: [String!]!, $billingType: String!,
|
||||
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
|
||||
upsertSub(oldName: $oldName, name: $name, desc: $desc, baseCost: $baseCost,
|
||||
postTypes: $postTypes, billingType: $billingType,
|
||||
replyCost: $replyCost, postTypes: $postTypes, billingType: $billingType,
|
||||
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
|
||||
result {
|
||||
name
|
||||
@ -279,10 +279,10 @@ export const UPSERT_SUB = gql`
|
||||
export const UNARCHIVE_TERRITORY = gql`
|
||||
${PAID_ACTION}
|
||||
mutation unarchiveTerritory($name: String!, $desc: String, $baseCost: Int!,
|
||||
$postTypes: [String!]!, $billingType: String!,
|
||||
$replyCost: Int!, $postTypes: [String!]!, $billingType: String!,
|
||||
$billingAutoRenew: Boolean!, $moderated: Boolean!, $nsfw: Boolean!) {
|
||||
unarchiveTerritory(name: $name, desc: $desc, baseCost: $baseCost,
|
||||
postTypes: $postTypes, billingType: $billingType,
|
||||
replyCost: $replyCost, postTypes: $postTypes, billingType: $billingType,
|
||||
billingAutoRenew: $billingAutoRenew, moderated: $moderated, nsfw: $nsfw) {
|
||||
result {
|
||||
name
|
||||
|
@ -25,6 +25,7 @@ export const SUB_FIELDS = gql`
|
||||
billedLastAt
|
||||
billPaidUntil
|
||||
baseCost
|
||||
replyCost
|
||||
userId
|
||||
desc
|
||||
status
|
||||
|
@ -317,6 +317,9 @@ export function territorySchema (args) {
|
||||
baseCost: intValidator
|
||||
.min(1, 'must be at least 1')
|
||||
.max(100000, 'must be at most 100k'),
|
||||
replyCost: intValidator
|
||||
.min(1, 'must be at least 1')
|
||||
.max(100000, 'must be at most 100k'),
|
||||
postTypes: array().of(string().oneOf(POST_TYPES)).min(1, 'must support at least one post type'),
|
||||
billingType: string().required('required').oneOf(TERRITORY_BILLING_TYPES, 'required'),
|
||||
nsfw: boolean()
|
||||
|
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Sub" ADD COLUMN "replyCost" INTEGER NOT NULL DEFAULT 1;
|
@ -737,6 +737,7 @@ model Sub {
|
||||
rankingType RankingType
|
||||
allowFreebies Boolean @default(true)
|
||||
baseCost Int @default(1)
|
||||
replyCost Int @default(1)
|
||||
rewardsPct Int @default(50)
|
||||
desc String?
|
||||
status Status @default(ACTIVE)
|
||||
|
Loading…
x
Reference in New Issue
Block a user