diff --git a/src/components/captcha/CaptchaInvisible.tsx b/src/components/captcha/CaptchaInvisible.tsx
index 14ba37c16..37d94f28e 100644
--- a/src/components/captcha/CaptchaInvisible.tsx
+++ b/src/components/captcha/CaptchaInvisible.tsx
@@ -1,5 +1,6 @@
import { getCaptchaSiteKey } from '@/utils/env/client'
import React, { useRef } from 'react'
+import { createPortal } from 'react-dom'
import ReCAPTCHA from 'react-google-recaptcha'
import { toast } from 'react-hot-toast'
import Toast from '../Toast'
@@ -38,13 +39,16 @@ export default function CaptchaInvisible({ children }: CaptchaInvisibleProps) {
{children(runCaptcha, (className) => (
))}
-
+ {createPortal(
+ ,
+ document.body
+ )}
>
)
}
diff --git a/src/components/chats/ChatItem/Embed.module.css b/src/components/chats/ChatItem/Embed.module.css
index 4ef1049e8..b60261e92 100644
--- a/src/components/chats/ChatItem/Embed.module.css
+++ b/src/components/chats/ChatItem/Embed.module.css
@@ -1,3 +1,4 @@
.Embed :global(.react-tweet-theme) {
--tweet-body-font-size: 1rem;
+ min-width: auto;
}
diff --git a/src/components/chats/ChatItem/Embed.tsx b/src/components/chats/ChatItem/Embed.tsx
index 214469dd3..80707b980 100644
--- a/src/components/chats/ChatItem/Embed.tsx
+++ b/src/components/chats/ChatItem/Embed.tsx
@@ -17,7 +17,7 @@ export default function Embed({ link: url, ...props }: EmbedProps) {
return (
Component && (
-
+
)
@@ -55,7 +55,8 @@ const urlMapper: {
)
},
checker: (link: string) =>
- /(?:https?:\/\/)?(?:www\.)?(?:twitter\.com)\/(.+)/.test(link),
+ /(?:https?:\/\/)?(?:www\.)?(?:twitter\.com)\/(.+)/.test(link) &&
+ /\/status\/\d+/.test(link),
},
{
name: 'tiktok',
diff --git a/src/components/chats/ChatItem/LinkPreview.tsx b/src/components/chats/ChatItem/LinkPreview.tsx
index 9858e477b..de41ed21a 100644
--- a/src/components/chats/ChatItem/LinkPreview.tsx
+++ b/src/components/chats/ChatItem/LinkPreview.tsx
@@ -39,6 +39,8 @@ export default function LinkPreview({
length: 300,
})
+ const isValidImage = linkMetadata.image?.startsWith('https://')
+
return (
{truncatedDesc}
- {linkMetadata.image && (
+ {linkMetadata.image && isValidImage && (
(
replicated.textContent = (props.value ?? '') + ' '
}, [props.value])
+ useEffect(() => {
+ const textArea = textAreaRef.current
+ const replicated = replicatedRef.current
+ if (!replicated || !textArea) return
+ replicated.textContent = textArea.value + ' '
+ }, [])
+
const onKeyDown: KeyboardEventHandler = (e) => {
if (!isTouchDevice() && e.key === 'Enter' && !e.shiftKey) {
e.preventDefault()
diff --git a/src/components/modals/MessageModal.tsx b/src/components/modals/MessageModal.tsx
index 7c0f44dd9..072a50d8e 100644
--- a/src/components/modals/MessageModal.tsx
+++ b/src/components/modals/MessageModal.tsx
@@ -78,29 +78,34 @@ export default function MessageModal({
>
{message && (
-
+
+
+
)}
{scrollToMessage && (
-
+
+
+
)}
{isDifferentRecipient && recipient && (
diff --git a/src/pages/api/posts.ts b/src/pages/api/posts.ts
index 41e8d89f1..cb1f252ba 100644
--- a/src/pages/api/posts.ts
+++ b/src/pages/api/posts.ts
@@ -134,6 +134,7 @@ export async function getPostsServer(postIds: string[]): Promise {
const getMetadataRedisKey = (url: string) => 'metadata:' + url
const METADATA_MAX_AGE = 60 * 60 * 24 * 30 // 1 month
+const METADATA_ERROR_MAX_AGE = 60 * 60 * 24 // 1 day
async function getLinkMetadata(link: string): Promise {
const cachedData = await redisCallWrapper((redis) =>
redis?.get(getMetadataRedisKey(link))
@@ -164,6 +165,14 @@ async function getLinkMetadata(link: string): Promise {
return parsedMetadata
} catch (err) {
console.error('Error fetching page metadata for link: ', link)
+ redisCallWrapper((redis) =>
+ redis?.set(
+ getMetadataRedisKey(link),
+ JSON.stringify(null),
+ 'EX',
+ METADATA_ERROR_MAX_AGE
+ )
+ )
return null
}
}
diff --git a/src/utils/ipfs.ts b/src/utils/ipfs.ts
index a00bce200..d0f6263ee 100644
--- a/src/utils/ipfs.ts
+++ b/src/utils/ipfs.ts
@@ -21,14 +21,18 @@ export function getIpfsContentUrl(
if (uri.startsWith('http')) return uri
- const ipfsCid = CID.parse(uri)
- if (!ipfsCid) return uri
-
- const isCbor = ipfsCid.code === CID_KIND.CBOR
- if (isCbor) {
- return urlJoin(SUBSOCIAL_IPFS_GATEWAY, `/api/v0/dag/get?arg=${uri}`)
- }
- return urlJoin(SUBSOCIAL_IPFS_GATEWAY, `/ipfs/${uri}`)
+ try {
+ const ipfsCid = CID.parse(uri)
+ if (!ipfsCid) return uri
+
+ const isCbor = ipfsCid.code === CID_KIND.CBOR
+ if (isCbor) {
+ return urlJoin(SUBSOCIAL_IPFS_GATEWAY, `/api/v0/dag/get?arg=${uri}`)
+ }
+ return urlJoin(SUBSOCIAL_IPFS_GATEWAY, `/ipfs/${uri}`)
+ } catch {}
+
+ return uri
}
export function getCidFromMetadataLink(link: string) {