{t('paste_signature')}
{
const account = useAccount();
const [cryptoState, setCryptoState] = useState({
- cryptoAddress: '',
+ cryptoAddress: account?.author?.shortAddress.includes('.') ? account.author.shortAddress : '',
checkingCryptoAddress: false,
showResolvingMessage: true,
resolveString: t('crypto_address_verification'),
@@ -62,6 +62,12 @@ const CryptoAddressSetting = () => {
if (!cryptoState.cryptoAddress || !cryptoState.cryptoAddress.includes('.')) {
alert(t('enter_crypto_address'));
return;
+ } else if (cryptoState.cryptoAddress === account?.author?.address) {
+ setSavedCryptoAddress(true);
+ setTimeout(() => {
+ setSavedCryptoAddress(false);
+ }, 2000);
+ return;
} else if (resolvedAddress && resolvedAddress !== account?.signer?.address) {
alert(t('crypto_address_not_yours'));
return;
@@ -110,7 +116,7 @@ const CryptoAddressSetting = () => {
{
setInputValue(e.target.value);
setCryptoState((prevState) => ({ ...prevState, cryptoAddress: e.target.value }));
diff --git a/src/components/settings-modal/plebbit-options/plebbit-options.tsx b/src/components/settings-modal/plebbit-options/plebbit-options.tsx
index b0ca7cd2..b6ccb5ae 100644
--- a/src/components/settings-modal/plebbit-options/plebbit-options.tsx
+++ b/src/components/settings-modal/plebbit-options/plebbit-options.tsx
@@ -12,7 +12,7 @@ interface SettingsProps {
maticRpcRef?: RefObject
;
avaxRpcRef?: RefObject;
plebbitRpcRef?: RefObject;
- nodeDataPathRef?: RefObject;
+ plebbitDataPathRef?: RefObject;
}
const IPFSGatewaysSettings = ({ ipfsGatewayUrlsRef, mediaIpfsGatewayUrlRef }: SettingsProps) => {
@@ -119,21 +119,23 @@ const PlebbitRPCSettings = ({ plebbitRpcRef }: SettingsProps) => {
);
};
-const NodeDataPathSettings = ({ nodeDataPathRef }: SettingsProps) => {
+const PlebbitDataPathSettings = ({ plebbitDataPathRef }: SettingsProps) => {
const plebbitRpc = usePlebbitRpcSettings();
const { plebbitRpcSettings } = plebbitRpc || {};
const isConnectedToRpc = plebbitRpc?.state === 'succeeded';
- const path = plebbitRpcSettings?.plebbitOptions?.dataPath || '';
+ const path = plebbitRpcSettings?.plebbitOptions?.plebbitDataPath || '';
return (
-
+
);
};
+const isElectron = window.isElectron === true;
+
const PlebbitOptions = () => {
const { t } = useTranslation();
const account = useAccount();
@@ -146,19 +148,50 @@ const PlebbitOptions = () => {
const solRpcRef = useRef
(null);
const maticRpcRef = useRef(null);
const avaxRpcRef = useRef(null);
+ const httpRoutersRef = useRef(null);
const plebbitRpcRef = useRef(null);
- const nodeDataPathRef = useRef(null);
+ const plebbitDataPathRef = useRef(null);
const handleSave = async () => {
- const ipfsGatewayUrls = ipfsGatewayUrlsRef.current?.value.split('\n').map((url) => url.trim());
+ const ipfsGatewayUrls = ipfsGatewayUrlsRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
const mediaIpfsGatewayUrl = mediaIpfsGatewayUrlRef.current?.value.trim();
- const pubsubHttpClientsOptions = pubsubProvidersRef.current?.value.split('\n').map((url) => url.trim());
- const ethRpcUrls = ethRpcRef.current?.value.split('\n').map((url) => url.trim());
- const solRpcUrls = solRpcRef.current?.value.split('\n').map((url) => url.trim());
- const maticRpcUrls = maticRpcRef.current?.value.split('\n').map((url) => url.trim());
- const avaxRpcUrls = avaxRpcRef.current?.value.split('\n').map((url) => url.trim());
- const plebbitRpcClientsOptions = plebbitRpcRef.current?.value.trim();
- const dataPath = nodeDataPathRef.current?.value.trim();
+
+ const pubsubHttpClientsOptions = pubsubProvidersRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const ethRpcUrls = ethRpcRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const solRpcUrls = solRpcRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const maticRpcUrls = maticRpcRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const avaxRpcUrls = avaxRpcRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const httpRoutersOptions = httpRoutersRef.current?.value
+ .split('\n')
+ .map((url) => url.trim())
+ .filter((url) => url !== '');
+
+ const plebbitRpcClientsOptions = plebbitRpcRef.current?.value.trim() ? [plebbitRpcRef.current.value.trim()] : undefined;
+ const dataPath = plebbitDataPathRef.current?.value.trim() || undefined;
const chainProviders = {
eth: {
@@ -188,11 +221,12 @@ const PlebbitOptions = () => {
ipfsGatewayUrls,
pubsubHttpClientsOptions,
chainProviders,
+ httpRoutersOptions,
plebbitRpcClientsOptions,
dataPath,
},
});
- alert('Options saved.');
+ alert('Options saved, reloading...');
window.location.reload();
} catch (e) {
if (e instanceof Error) {
@@ -230,17 +264,19 @@ const PlebbitOptions = () => {
-
node RPC:
+
plebbit RPC:
-
- node data path:
-
-
-
-
+ {isElectron && (
+
+
plebbit data path:
+
+
+
+
+ )}
);
};
diff --git a/src/hooks/use-comment-media-info.ts b/src/hooks/use-comment-media-info.ts
new file mode 100644
index 00000000..3a724b30
--- /dev/null
+++ b/src/hooks/use-comment-media-info.ts
@@ -0,0 +1,44 @@
+import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useLocation, useParams } from 'react-router-dom';
+import { Comment } from '@plebbit/plebbit-react-hooks';
+import { getCommentMediaInfo, fetchWebpageThumbnailIfNeeded } from '../lib/utils/media-utils';
+import { isPendingPostView, isPostPageView } from '../lib/utils/view-utils';
+
+export const useCommentMediaInfo = (comment: Comment) => {
+ const location = useLocation();
+ const params = useParams();
+ const isInPostPageView = isPostPageView(location.pathname, params);
+ const isInPendingPostView = isPendingPostView(location.pathname, params);
+ // some sites have CORS access, so the thumbnail can be fetched client-side, which is helpful if subplebbit.settings.fetchThumbnailUrls is false
+ const initialCommentMediaInfo = useMemo(() => getCommentMediaInfo(comment), [comment]);
+ const [commentMediaInfo, setCommentMediaInfo] = useState(initialCommentMediaInfo);
+
+ const fetchThumbnail = useCallback(async () => {
+ if (!isInPostPageView && !isInPendingPostView) {
+ return; // don't fetch in feed view, it displaces the posts
+ }
+ if (initialCommentMediaInfo?.type === 'webpage' && !initialCommentMediaInfo.thumbnail) {
+ const newMediaInfo = await fetchWebpageThumbnailIfNeeded(initialCommentMediaInfo);
+
+ // Fetch the dimensions of the thumbnail
+ if (newMediaInfo.thumbnail) {
+ const img = new Image();
+ img.onload = () => {
+ setCommentMediaInfo({
+ ...newMediaInfo,
+ thumbnailWidth: img.width,
+ thumbnailHeight: img.height,
+ });
+ };
+ img.src = newMediaInfo.thumbnail;
+ } else {
+ setCommentMediaInfo(newMediaInfo);
+ }
+ }
+ }, [initialCommentMediaInfo, isInPostPageView, isInPendingPostView]);
+ useEffect(() => {
+ fetchThumbnail();
+ }, [fetchThumbnail]);
+
+ return commentMediaInfo;
+};
diff --git a/src/hooks/use-fetch-gif-first-frame.ts b/src/hooks/use-fetch-gif-first-frame.ts
index 88c85bd3..f936caae 100644
--- a/src/hooks/use-fetch-gif-first-frame.ts
+++ b/src/hooks/use-fetch-gif-first-frame.ts
@@ -75,8 +75,13 @@ const useFetchGifFirstFrame = (url: string | undefined) => {
try {
const cachedFrame = await getCachedGifFrame(url);
if (cachedFrame) {
- if (isActive) setFrameUrl(cachedFrame);
- return;
+ try {
+ const response = await fetch(cachedFrame);
+ if (response.ok) {
+ if (isActive) setFrameUrl(cachedFrame);
+ return;
+ }
+ } catch {}
}
const blob = typeof url === 'string' ? await parseGif(await fetchImage(url)) : await parseGif(await readImage(url as File));
diff --git a/src/lib/utils/media-utils.ts b/src/lib/utils/media-utils.ts
index d61dbe58..0acafe0b 100644
--- a/src/lib/utils/media-utils.ts
+++ b/src/lib/utils/media-utils.ts
@@ -10,6 +10,8 @@ export interface CommentMediaInfo {
url: string;
type: string;
thumbnail?: string;
+ thumbnailWidth?: number;
+ thumbnailHeight?: number;
patternThumbnailUrl?: string;
post?: Comment;
}