a tool for shared writing and social publishing

add button blocks to published posts

+141 -9
+19 -4
actions/publishToPublication.ts
··· 23 23 PubLeafletBlocksIframe, 24 24 PubLeafletBlocksPage, 25 25 PubLeafletBlocksPoll, 26 + PubLeafletBlocksButton, 26 27 PubLeafletPollDefinition, 27 28 } from "lexicons/api"; 28 29 import { Block } from "components/Blocks/Block"; ··· 192 193 await Promise.all( 193 194 parsedBlocks.map(async (blockOrList) => { 194 195 if (blockOrList.type === "block") { 195 - let alignmentValue = 196 - scan.eav(blockOrList.block.value, "block/text-alignment")[0]?.data 197 - .value || "left"; 196 + let alignmentValue = scan.eav( 197 + blockOrList.block.value, 198 + "block/text-alignment", 199 + )[0]?.data.value; 198 200 let alignment: ExcludeString< 199 201 PubLeafletPagesLinearDocument.Block["alignment"] 200 202 > = ··· 204 206 ? "lex:pub.leaflet.pages.linearDocument#textAlignRight" 205 207 : alignmentValue === "justify" 206 208 ? "lex:pub.leaflet.pages.linearDocument#textAlignJustify" 207 - : undefined; 209 + : alignmentValue === "left" 210 + ? "lex:pub.leaflet.pages.linearDocument#textAlignLeft" 211 + : undefined; 208 212 let b = await blockToRecord(blockOrList.block, did); 209 213 if (!b) return []; 210 214 let block: PubLeafletPagesLinearDocument.Block = { ··· 447 451 uri: pollResult.uri, 448 452 cid: pollResult.cid, 449 453 }, 454 + }; 455 + return block; 456 + } 457 + if (b.type === "button") { 458 + let [text] = scan.eav(b.value, "button/text"); 459 + let [url] = scan.eav(b.value, "button/url"); 460 + if (!text || !url) return; 461 + let block: $Typed<PubLeafletBlocksButton.Main> = { 462 + $type: "pub.leaflet.blocks.button", 463 + text: text.data.value, 464 + url: url.data.value, 450 465 }; 451 466 return block; 452 467 }
+21 -2
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
··· 16 16 PubLeafletBlocksIframe, 17 17 PubLeafletBlocksPage, 18 18 PubLeafletBlocksPoll, 19 + PubLeafletBlocksButton, 19 20 } from "lexicons/api"; 20 21 21 22 import { blobRefToSrc } from "src/utils/blobRefToSrc"; ··· 32 33 import { PublishedPageLinkBlock } from "./PublishedPageBlock"; 33 34 import { PublishedPollBlock } from "./PublishedPollBlock"; 34 35 import { PollData } from "./fetchPollData"; 36 + import { ButtonPrimary } from "components/Buttons"; 35 37 36 38 export function PostContent({ 37 39 blocks, ··· 128 130 : b.alignment === 129 131 "lex:pub.leaflet.pages.linearDocument#textAlignJustify" 130 132 ? "text-justify justify-start" 131 - : ""; 132 - if (!alignment && PubLeafletBlocksImage.isMain(b.block)) 133 + : b.alignment === "lex:pub.leaflet.pages.linearDocument#textAlignLeft" 134 + ? "text-left justify-start" 135 + : undefined; 136 + if ( 137 + !alignment && 138 + (PubLeafletBlocksImage.isMain(b.block) || 139 + PubLeafletBlocksButton.isMain(b.block)) 140 + ) 133 141 alignment = "text-center justify-center"; 134 142 135 143 let className = ` ··· 192 200 className={className} 193 201 pollData={pollVoteData} 194 202 /> 203 + ); 204 + } 205 + case PubLeafletBlocksButton.isMain(b.block): { 206 + return ( 207 + <div className={`flex ${alignment} ${className}`} {...blockProps}> 208 + <a href={b.block.url} target="_blank" rel="noopener noreferrer"> 209 + <ButtonPrimary role="link" type="submit"> 210 + {b.block.text} 211 + </ButtonPrimary> 212 + </a> 213 + </div> 195 214 ); 196 215 } 197 216 case PubLeafletBlocksUnorderedList.isMain(b.block): {
-1
components/Blocks/BlockCommands.tsx
··· 204 204 name: "Button", 205 205 icon: <BlockButtonSmall />, 206 206 type: "block", 207 - hiddenInPublication: true, 208 207 onSelect: async (rep, props, um) => { 209 208 props.entityID && clearCommandSearchText(props.entityID); 210 209 await createBlockWithType(rep, props, "button");
+2
lexicons/api/index.ts
··· 25 25 import * as ComAtprotoRepoUploadBlob from './types/com/atproto/repo/uploadBlob' 26 26 import * as PubLeafletBlocksBlockquote from './types/pub/leaflet/blocks/blockquote' 27 27 import * as PubLeafletBlocksBskyPost from './types/pub/leaflet/blocks/bskyPost' 28 + import * as PubLeafletBlocksButton from './types/pub/leaflet/blocks/button' 28 29 import * as PubLeafletBlocksCode from './types/pub/leaflet/blocks/code' 29 30 import * as PubLeafletBlocksHeader from './types/pub/leaflet/blocks/header' 30 31 import * as PubLeafletBlocksHorizontalRule from './types/pub/leaflet/blocks/horizontalRule' ··· 64 65 export * as ComAtprotoRepoUploadBlob from './types/com/atproto/repo/uploadBlob' 65 66 export * as PubLeafletBlocksBlockquote from './types/pub/leaflet/blocks/blockquote' 66 67 export * as PubLeafletBlocksBskyPost from './types/pub/leaflet/blocks/bskyPost' 68 + export * as PubLeafletBlocksButton from './types/pub/leaflet/blocks/button' 67 69 export * as PubLeafletBlocksCode from './types/pub/leaflet/blocks/code' 68 70 export * as PubLeafletBlocksHeader from './types/pub/leaflet/blocks/header' 69 71 export * as PubLeafletBlocksHorizontalRule from './types/pub/leaflet/blocks/horizontalRule'
+22
lexicons/api/lexicons.ts
··· 1052 1052 }, 1053 1053 }, 1054 1054 }, 1055 + PubLeafletBlocksButton: { 1056 + lexicon: 1, 1057 + id: 'pub.leaflet.blocks.button', 1058 + defs: { 1059 + main: { 1060 + type: 'object', 1061 + required: ['text', 'url'], 1062 + properties: { 1063 + text: { 1064 + type: 'string', 1065 + }, 1066 + url: { 1067 + type: 'string', 1068 + format: 'uri', 1069 + }, 1070 + }, 1071 + }, 1072 + }, 1073 + }, 1055 1074 PubLeafletBlocksCode: { 1056 1075 lexicon: 1, 1057 1076 id: 'pub.leaflet.blocks.code', ··· 1493 1512 'lex:pub.leaflet.blocks.bskyPost', 1494 1513 'lex:pub.leaflet.blocks.page', 1495 1514 'lex:pub.leaflet.blocks.poll', 1515 + 'lex:pub.leaflet.blocks.button', 1496 1516 ], 1497 1517 }, 1498 1518 x: { ··· 1593 1613 'lex:pub.leaflet.blocks.bskyPost', 1594 1614 'lex:pub.leaflet.blocks.page', 1595 1615 'lex:pub.leaflet.blocks.poll', 1616 + 'lex:pub.leaflet.blocks.button', 1596 1617 ], 1597 1618 }, 1598 1619 alignment: { ··· 2053 2074 ComAtprotoRepoUploadBlob: 'com.atproto.repo.uploadBlob', 2054 2075 PubLeafletBlocksBlockquote: 'pub.leaflet.blocks.blockquote', 2055 2076 PubLeafletBlocksBskyPost: 'pub.leaflet.blocks.bskyPost', 2077 + PubLeafletBlocksButton: 'pub.leaflet.blocks.button', 2056 2078 PubLeafletBlocksCode: 'pub.leaflet.blocks.code', 2057 2079 PubLeafletBlocksHeader: 'pub.leaflet.blocks.header', 2058 2080 PubLeafletBlocksHorizontalRule: 'pub.leaflet.blocks.horizontalRule',
+31
lexicons/api/types/pub/leaflet/blocks/button.ts
··· 1 + /** 2 + * GENERATED CODE - DO NOT MODIFY 3 + */ 4 + import { type ValidationResult, BlobRef } from '@atproto/lexicon' 5 + import { CID } from 'multiformats/cid' 6 + import { validate as _validate } from '../../../../lexicons' 7 + import { 8 + type $Typed, 9 + is$typed as _is$typed, 10 + type OmitKey, 11 + } from '../../../../util' 12 + 13 + const is$typed = _is$typed, 14 + validate = _validate 15 + const id = 'pub.leaflet.blocks.button' 16 + 17 + export interface Main { 18 + $type?: 'pub.leaflet.blocks.button' 19 + text: string 20 + url: string 21 + } 22 + 23 + const hashMain = 'main' 24 + 25 + export function isMain<V>(v: V) { 26 + return is$typed(v, id, hashMain) 27 + } 28 + 29 + export function validateMain<V>(v: V) { 30 + return validate<Main & V>(v, id, hashMain) 31 + }
+2
lexicons/api/types/pub/leaflet/pages/canvas.ts
··· 22 22 import type * as PubLeafletBlocksBskyPost from '../blocks/bskyPost' 23 23 import type * as PubLeafletBlocksPage from '../blocks/page' 24 24 import type * as PubLeafletBlocksPoll from '../blocks/poll' 25 + import type * as PubLeafletBlocksButton from '../blocks/button' 25 26 26 27 const is$typed = _is$typed, 27 28 validate = _validate ··· 59 60 | $Typed<PubLeafletBlocksBskyPost.Main> 60 61 | $Typed<PubLeafletBlocksPage.Main> 61 62 | $Typed<PubLeafletBlocksPoll.Main> 63 + | $Typed<PubLeafletBlocksButton.Main> 62 64 | { $type: string } 63 65 x: number 64 66 y: number
+2
lexicons/api/types/pub/leaflet/pages/linearDocument.ts
··· 22 22 import type * as PubLeafletBlocksBskyPost from '../blocks/bskyPost' 23 23 import type * as PubLeafletBlocksPage from '../blocks/page' 24 24 import type * as PubLeafletBlocksPoll from '../blocks/poll' 25 + import type * as PubLeafletBlocksButton from '../blocks/button' 25 26 26 27 const is$typed = _is$typed, 27 28 validate = _validate ··· 59 60 | $Typed<PubLeafletBlocksBskyPost.Main> 60 61 | $Typed<PubLeafletBlocksPage.Main> 61 62 | $Typed<PubLeafletBlocksPoll.Main> 63 + | $Typed<PubLeafletBlocksButton.Main> 62 64 | { $type: string } 63 65 alignment?: 64 66 | 'lex:pub.leaflet.pages.linearDocument#textAlignLeft'
+22
lexicons/pub/leaflet/blocks/button.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.button", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [ 8 + "text", 9 + "url" 10 + ], 11 + "properties": { 12 + "text": { 13 + "type": "string" 14 + }, 15 + "url": { 16 + "type": "string", 17 + "format": "uri" 18 + } 19 + } 20 + } 21 + } 22 + }
+2 -1
lexicons/pub/leaflet/pages/canvas.json
··· 44 44 "pub.leaflet.blocks.horizontalRule", 45 45 "pub.leaflet.blocks.bskyPost", 46 46 "pub.leaflet.blocks.page", 47 - "pub.leaflet.blocks.poll" 47 + "pub.leaflet.blocks.poll", 48 + "pub.leaflet.blocks.button" 48 49 ] 49 50 }, 50 51 "x": {
+2 -1
lexicons/pub/leaflet/pages/linearDocument.json
··· 41 41 "pub.leaflet.blocks.horizontalRule", 42 42 "pub.leaflet.blocks.bskyPost", 43 43 "pub.leaflet.blocks.page", 44 - "pub.leaflet.blocks.poll" 44 + "pub.leaflet.blocks.poll", 45 + "pub.leaflet.blocks.button" 45 46 ] 46 47 }, 47 48 "alignment": {
+16
lexicons/src/blocks.ts
··· 279 279 }, 280 280 }; 281 281 282 + export const PubLeafletBlocksButton: LexiconDoc = { 283 + lexicon: 1, 284 + id: "pub.leaflet.blocks.button", 285 + defs: { 286 + main: { 287 + type: "object", 288 + required: ["text", "url"], 289 + properties: { 290 + text: { type: "string" }, 291 + url: { type: "string", format: "uri" }, 292 + }, 293 + }, 294 + }, 295 + }; 296 + 282 297 export const BlockLexicons = [ 283 298 PubLeafletBlocksIFrame, 284 299 PubLeafletBlocksText, ··· 293 308 PubLeafletBlocksBskyPost, 294 309 PubLeafletBlocksPage, 295 310 PubLeafletBlocksPoll, 311 + PubLeafletBlocksButton, 296 312 ]; 297 313 export const BlockUnion: LexRefUnion = { 298 314 type: "union",