bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
17 lines • 6.33 kB
JSON
{
"name": "social-hooks-uselikepost",
"type": "registry:hook",
"dependencies": [
"@tanstack/react-query"
],
"devDependencies": [],
"registryDependencies": [],
"files": [
{
"path": "components/social/hooks/useLikePost.ts",
"type": "registry:hook",
"content": "// useLikePost Hook - Like/unlike posts with emoji reactions\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useBitcoinAuth } from \"../../../hooks/useBitcoinAuth.js\";\nimport { broadcastSocialTransaction } from \"../../../lib/broadcast\";\nimport { SocialActions } from \"../../../lib/protocol.js\";\nimport type { LikeMutationData, UseLikePostResult } from \"../types/hooks.js\";\nimport type {\n\tAuthUserWithSigning,\n\tBroadcastResult,\n\tSocialError,\n} from \"../types/social.js\";\n\ninterface UseLikePostOptions {\n\tapp?: string;\n\tonSuccess?: (result: BroadcastResult) => void;\n\tonError?: (error: SocialError) => void;\n}\n\nexport function useLikePost(\n\toptions: UseLikePostOptions = {},\n): UseLikePostResult {\n\tconst { app: _app = \"bigblocks\", onSuccess, onError } = options;\n\tconst { user } = useBitcoinAuth();\n\n\tconst likeMutation = useMutation<\n\t\tBroadcastResult,\n\t\tSocialError,\n\t\tLikeMutationData\n\t>({\n\t\tmutationFn: async ({ txid, emoji: _emoji = \"❤\" }) => {\n\t\t\tif (!user) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\tmessage: \"User must be authenticated to like posts\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\tif (!txid) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"INVALID_CONTENT\",\n\t\t\t\t\tmessage: \"Transaction ID is required to like a post\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\t// Validate txid format (64 character hex string)\n\t\t\tif (!/^[a-fA-F0-9]{64}$/.test(txid)) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"INVALID_CONTENT\",\n\t\t\t\t\tmessage: \"Invalid transaction ID format\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst signingKey = (user as AuthUserWithSigning).signingKey;\n\t\t\t\tif (!signingKey) {\n\t\t\t\t\tthrow {\n\t\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\t\tmessage: \"No signing key available\",\n\t\t\t\t\t} as SocialError;\n\t\t\t\t}\n\n\t\t\t\t// Build like transaction\n\t\t\t\tconst signedTransaction = await SocialActions.like(txid, _emoji);\n\n\t\t\t\t// Broadcast to Bitcoin network\n\t\t\t\tconst result = await broadcastSocialTransaction(signedTransaction);\n\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tthrow {\n\t\t\t\t\t\tcode: \"BROADCAST_FAILED\",\n\t\t\t\t\t\tmessage: result.error || \"Failed to broadcast like\",\n\t\t\t\t\t} as SocialError;\n\t\t\t\t}\n\n\t\t\t\treturn { ...result, transaction: signedTransaction };\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as SocialError).code) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"TRANSACTION_FAILED\",\n\t\t\t\t\tmessage: \"Failed to create like transaction\",\n\t\t\t\t\tdetails: error,\n\t\t\t\t} as SocialError;\n\t\t\t}\n\t\t},\n\t\tonSuccess: (data) => {\n\t\t\tonSuccess?.(data);\n\t\t},\n\t\tonError: (error) => {\n\t\t\tconsole.error(\"Like post failed:\", error);\n\t\t\tonError?.(error);\n\t\t},\n\t});\n\n\treturn {\n\t\tmutate: likeMutation.mutate,\n\t\tmutateAsync: likeMutation.mutateAsync,\n\t\tisLoading: likeMutation.isPending,\n\t\tisError: likeMutation.isError,\n\t\tisSuccess: likeMutation.isSuccess,\n\t\terror: likeMutation.error,\n\t\tdata: likeMutation.data,\n\t\treset: likeMutation.reset,\n\t} as UseLikePostResult;\n}\n\n// Unlike hook\nexport function useUnlikePost(options: UseLikePostOptions = {}) {\n\tconst { app: _app = \"bigblocks\", onSuccess, onError } = options;\n\tconst { user } = useBitcoinAuth();\n\n\treturn useMutation<BroadcastResult, SocialError, LikeMutationData>({\n\t\tmutationFn: async ({ txid, emoji: _emoji = \"❤\" }) => {\n\t\t\tif (!user) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\tmessage: \"User must be authenticated to unlike posts\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\tif (!txid) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"INVALID_CONTENT\",\n\t\t\t\t\tmessage: \"Transaction ID is required to unlike a post\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\tif (!/^[a-fA-F0-9]{64}$/.test(txid)) {\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"INVALID_CONTENT\",\n\t\t\t\t\tmessage: \"Invalid transaction ID format\",\n\t\t\t\t} as SocialError;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst signingKey = (user as AuthUserWithSigning).signingKey;\n\t\t\t\tif (!signingKey) {\n\t\t\t\t\tthrow {\n\t\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\t\tmessage: \"No signing key available\",\n\t\t\t\t\t} as SocialError;\n\t\t\t\t}\n\n\t\t\t\t// Build unlike transaction\n\t\t\t\tconst signedTransaction = await SocialActions.unlike(txid);\n\n\t\t\t\t// Broadcast to Bitcoin network\n\t\t\t\tconst result = await broadcastSocialTransaction(signedTransaction);\n\n\t\t\t\tif (!result.success) {\n\t\t\t\t\tthrow {\n\t\t\t\t\t\tcode: \"BROADCAST_FAILED\",\n\t\t\t\t\t\tmessage: result.error || \"Failed to broadcast unlike\",\n\t\t\t\t\t} as SocialError;\n\t\t\t\t}\n\n\t\t\t\treturn { ...result, transaction: signedTransaction };\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as SocialError).code) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\n\t\t\t\tthrow {\n\t\t\t\t\tcode: \"TRANSACTION_FAILED\",\n\t\t\t\t\tmessage: \"Failed to create unlike transaction\",\n\t\t\t\t\tdetails: error,\n\t\t\t\t} as SocialError;\n\t\t\t}\n\t\t},\n\t\tonSuccess: (data) => {\n\t\t\tonSuccess?.(data);\n\t\t},\n\t\tonError: (error) => {\n\t\t\tconsole.error(\"Unlike post failed:\", error);\n\t\t\tonError?.(error);\n\t\t},\n\t});\n}\n\n// Combined hook for toggling likes\nexport function useToggleLike(options: UseLikePostOptions = {}) {\n\tconst likePost = useLikePost(options);\n\tconst unlikePostMutation = useUnlikePost(options);\n\n\treturn {\n\t\tlike: likePost,\n\t\tunlike: unlikePostMutation,\n\t\ttoggle: (txid: string, emoji: string, currentlyLiked: boolean) => {\n\t\t\tif (currentlyLiked) {\n\t\t\t\treturn unlikePostMutation.mutate({ txid, emoji });\n\t\t\t}\n\t\t\treturn likePost.mutate({ txid, emoji });\n\t\t},\n\t\tisLoading: likePost.isLoading || unlikePostMutation.isPending,\n\t\terror: likePost.error || unlikePostMutation.error,\n\t};\n}\n",
"target": "<%- config.aliases.hooks %>/uselikepost.ts"
}
]
}