mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at verify-code 4.6 kB view raw
1import {AppBskyFeedDefs, AppBskyFeedThreadgate} from '@atproto/api' 2 3import {ThreadgateAllowUISetting} from '#/state/queries/threadgate/types' 4 5export function threadgateViewToAllowUISetting( 6 threadgateView: AppBskyFeedDefs.ThreadgateView | undefined, 7): ThreadgateAllowUISetting[] { 8 const threadgate = 9 threadgateView && 10 AppBskyFeedThreadgate.isRecord(threadgateView.record) && 11 AppBskyFeedThreadgate.validateRecord(threadgateView.record).success 12 ? threadgateView.record 13 : undefined 14 return threadgateRecordToAllowUISetting(threadgate) 15} 16 17/** 18 * Converts a full {@link AppBskyFeedThreadgate.Record} to a list of 19 * {@link ThreadgateAllowUISetting}, for use by app UI. 20 */ 21export function threadgateRecordToAllowUISetting( 22 threadgate: AppBskyFeedThreadgate.Record | undefined, 23): ThreadgateAllowUISetting[] { 24 /* 25 * If `threadgate` doesn't exist (default), or if `threadgate.allow === undefined`, it means 26 * anyone can reply. 27 * 28 * If `threadgate.allow === []` it means no one can reply, and we translate to UI code 29 * here. This was a historical choice, and we have no lexicon representation 30 * for 'replies disabled' other than an empty array. 31 */ 32 if (!threadgate || threadgate.allow === undefined) { 33 return [{type: 'everybody'}] 34 } 35 if (threadgate.allow.length === 0) { 36 return [{type: 'nobody'}] 37 } 38 39 const settings: ThreadgateAllowUISetting[] = threadgate.allow 40 .map(allow => { 41 let setting: ThreadgateAllowUISetting | undefined 42 if (allow.$type === 'app.bsky.feed.threadgate#mentionRule') { 43 setting = {type: 'mention'} 44 } else if (allow.$type === 'app.bsky.feed.threadgate#followingRule') { 45 setting = {type: 'following'} 46 } else if (allow.$type === 'app.bsky.feed.threadgate#listRule') { 47 setting = {type: 'list', list: allow.list} 48 } 49 return setting 50 }) 51 .filter(n => !!n) 52 return settings 53} 54 55/** 56 * Converts an array of {@link ThreadgateAllowUISetting} to the `allow` prop on 57 * {@link AppBskyFeedThreadgate.Record}. 58 * 59 * If the `allow` property on the record is undefined, we infer that to mean 60 * that everyone can reply. If it's an empty array, we infer that to mean that 61 * no one can reply. 62 */ 63export function threadgateAllowUISettingToAllowRecordValue( 64 threadgate: ThreadgateAllowUISetting[], 65): AppBskyFeedThreadgate.Record['allow'] { 66 if (threadgate.find(v => v.type === 'everybody')) { 67 return undefined 68 } 69 70 let allow: ( 71 | AppBskyFeedThreadgate.MentionRule 72 | AppBskyFeedThreadgate.FollowingRule 73 | AppBskyFeedThreadgate.ListRule 74 )[] = [] 75 76 if (!threadgate.find(v => v.type === 'nobody')) { 77 for (const rule of threadgate) { 78 if (rule.type === 'mention') { 79 allow.push({$type: 'app.bsky.feed.threadgate#mentionRule'}) 80 } else if (rule.type === 'following') { 81 allow.push({$type: 'app.bsky.feed.threadgate#followingRule'}) 82 } else if (rule.type === 'list') { 83 allow.push({ 84 $type: 'app.bsky.feed.threadgate#listRule', 85 list: rule.list, 86 }) 87 } 88 } 89 } 90 91 return allow 92} 93 94/** 95 * Merges two {@link AppBskyFeedThreadgate.Record} objects, combining their 96 * `allow` and `hiddenReplies` arrays and de-deduplicating them. 97 * 98 * Note: `allow` can be undefined here, be sure you don't accidentally set it 99 * to an empty array. See other comments in this file. 100 */ 101export function mergeThreadgateRecords( 102 prev: AppBskyFeedThreadgate.Record, 103 next: Partial<AppBskyFeedThreadgate.Record>, 104): AppBskyFeedThreadgate.Record { 105 // can be undefined if everyone can reply! 106 const allow: AppBskyFeedThreadgate.Record['allow'] | undefined = 107 prev.allow || next.allow 108 ? [...(prev.allow || []), ...(next.allow || [])].filter( 109 (v, i, a) => a.findIndex(t => t.$type === v.$type) === i, 110 ) 111 : undefined 112 const hiddenReplies = Array.from( 113 new Set([...(prev.hiddenReplies || []), ...(next.hiddenReplies || [])]), 114 ) 115 116 return createThreadgateRecord({ 117 post: prev.post, 118 allow, // can be undefined! 119 hiddenReplies, 120 }) 121} 122 123/** 124 * Create a new {@link AppBskyFeedThreadgate.Record} object with the given 125 * properties. 126 */ 127export function createThreadgateRecord( 128 threadgate: Partial<AppBskyFeedThreadgate.Record>, 129): AppBskyFeedThreadgate.Record { 130 if (!threadgate.post) { 131 throw new Error('Cannot create a threadgate record without a post URI') 132 } 133 134 return { 135 $type: 'app.bsky.feed.threadgate', 136 post: threadgate.post, 137 createdAt: new Date().toISOString(), 138 allow: threadgate.allow, // can be undefined! 139 hiddenReplies: threadgate.hiddenReplies || [], 140 } 141}