From e791d084aa48b2e4a7ba105c1e327daba80af42f Mon Sep 17 00:00:00 2001 From: rannyeribaptist Date: Wed, 6 Jul 2022 12:00:13 -0300 Subject: [PATCH 1/5] whitelist of images by token ID --- src/components/_General/TokenMediaDisplay.tsx | 83 +++++++++++++------ 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/src/components/_General/TokenMediaDisplay.tsx b/src/components/_General/TokenMediaDisplay.tsx index 252c3925..1de01bd7 100644 --- a/src/components/_General/TokenMediaDisplay.tsx +++ b/src/components/_General/TokenMediaDisplay.tsx @@ -5,7 +5,12 @@ import { ipcRenderer } from 'electron'; import { Responsive, extractIPFSHash } from 'util/helpers'; import { V } from 'util/theming'; -import { DEFAULT_IPFS_FALLBACK_GATEWAY, IPFS_IPC_ID, IpfsAction } from 'vars/defines'; +import { + DEFAULT_IPFS_FALLBACK_GATEWAY, + IPFS_IPC_ID, + IpfsAction, + TOKEN_WHITE_LIST_LOCATION, +} from 'vars/defines'; const MediaContent = styled.div` overflow-y: auto; @@ -40,29 +45,38 @@ const TokenMediaDisplay: React.FC = ({ url }) => { const [mediaUrl, setMediaUrl] = useState(null); const ipfsId = useMemo(() => extractIPFSHash(url), [url]); + const tokenAddress = ipfsId || url; + const tokenInWhiteList = + JSON.parse(localStorage.getItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`)) || false; + + const [mediaShouldLoad, setMediaShouldLoad] = useState(tokenInWhiteList); useEffect(() => { setIframeHeight('unset'); setMediaUrl(null); + setIframeLoaded(false); + setMediaShouldLoad(tokenInWhiteList); iframeRef.current?.contentWindow.postMessage({ mediaUrl: '', width: 0 }); - }, [url]); + }, [url, tokenInWhiteList]); // Request IPFS file if it's an IPFS link. Set link meanwhile anyway useEffect(() => { - if (ipfsId) { - ipcRenderer.send(IPFS_IPC_ID, { - type: IpfsAction.GET, - payload: { - ipfsId, - }, - }); - - // Set fallback in case IPFS data never streams to our node - setMediaUrl(`${DEFAULT_IPFS_FALLBACK_GATEWAY}/${ipfsId}`); - } else { - setMediaUrl(url); + if (iframeLoaded) { + if (ipfsId) { + ipcRenderer.send(IPFS_IPC_ID, { + type: IpfsAction.GET, + payload: { + ipfsId, + }, + }); + + // Set fallback in case IPFS data never streams to our node + setMediaUrl(`${DEFAULT_IPFS_FALLBACK_GATEWAY}/${ipfsId}`); + } else { + setMediaUrl(url); + } } - }, [url, ipfsId]); + }, [url, ipfsId, iframeLoaded]); // Listen for IPFS files useEffect(() => { @@ -107,19 +121,36 @@ const TokenMediaDisplay: React.FC = ({ url }) => { }; }, [iframeRef, iframeLoaded]); - if (!mediaUrl) return null; + function addTokenToWhiteList() { + localStorage.setItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`, 'true'); + setMediaShouldLoad(true); + } return ( - - - setIframeLoaded(true)} - /> - - + <> + {mediaShouldLoad && ( + + + setIframeLoaded(true)} + /> + + + )} + {!mediaShouldLoad && ( + <> + + + + )} + ); }; From ebf3575bb14dfa7e2a722a7381f465f3ca29ca96 Mon Sep 17 00:00:00 2001 From: rannyeribaptist Date: Tue, 12 Jul 2022 15:19:52 -0300 Subject: [PATCH 2/5] Created local storage whitelist for NFTs --- src/components/_General/TokenMediaDisplay.tsx | 70 ++++++++++++++----- src/vars/defines.ts | 2 + 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/components/_General/TokenMediaDisplay.tsx b/src/components/_General/TokenMediaDisplay.tsx index 1de01bd7..200d5537 100644 --- a/src/components/_General/TokenMediaDisplay.tsx +++ b/src/components/_General/TokenMediaDisplay.tsx @@ -12,6 +12,8 @@ import { TOKEN_WHITE_LIST_LOCATION, } from 'vars/defines'; +import { ButtonSmall } from 'components/_General/buttons'; + const MediaContent = styled.div` overflow-y: auto; display: flex; @@ -34,6 +36,18 @@ const TokenMediaIframe = styled.iframe` border: 0; `; +const ButtonWrapper = styled.div` + display: flex; + justify-content: space-between; + margin-top: 25px; +`; + +const DisclaimerText = styled.p` + text-align: justify; + text-align-last: center; + font-size: 0.9rem; +`; + interface TokenMediaDisplayProps { url?: string; } @@ -43,25 +57,27 @@ const TokenMediaDisplay: React.FC = ({ url }) => { const [iframeLoaded, setIframeLoaded] = useState(false); const [iframeHeight, setIframeHeight] = useState('unset'); const [mediaUrl, setMediaUrl] = useState(null); + const [mediaShouldLoad, setMediaShouldLoad] = useState(false); const ipfsId = useMemo(() => extractIPFSHash(url), [url]); const tokenAddress = ipfsId || url; - const tokenInWhiteList = - JSON.parse(localStorage.getItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`)) || false; - - const [mediaShouldLoad, setMediaShouldLoad] = useState(tokenInWhiteList); + const tokenInWhiteList = !!localStorage.getItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`); useEffect(() => { setIframeHeight('unset'); setMediaUrl(null); setIframeLoaded(false); - setMediaShouldLoad(tokenInWhiteList); + setMediaShouldLoad(false); iframeRef.current?.contentWindow.postMessage({ mediaUrl: '', width: 0 }); - }, [url, tokenInWhiteList]); + }, [url]); + + useEffect(() => { + if (tokenInWhiteList && !iframeLoaded) setMediaShouldLoad(true); + }, [tokenInWhiteList, iframeLoaded]); // Request IPFS file if it's an IPFS link. Set link meanwhile anyway useEffect(() => { - if (iframeLoaded) { + if (mediaShouldLoad) { if (ipfsId) { ipcRenderer.send(IPFS_IPC_ID, { type: IpfsAction.GET, @@ -76,7 +92,7 @@ const TokenMediaDisplay: React.FC = ({ url }) => { setMediaUrl(url); } } - }, [url, ipfsId, iframeLoaded]); + }, [url, ipfsId, mediaShouldLoad]); // Listen for IPFS files useEffect(() => { @@ -119,10 +135,10 @@ const TokenMediaDisplay: React.FC = ({ url }) => { return () => { if (observer) observer.disconnect(); }; - }, [iframeRef, iframeLoaded]); + }, [iframeRef]); function addTokenToWhiteList() { - localStorage.setItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`, 'true'); + localStorage.setItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`, `${tokenAddress}`); setMediaShouldLoad(true); } @@ -135,19 +151,39 @@ const TokenMediaDisplay: React.FC = ({ url }) => { height={iframeHeight} ref={iframeRef} src={`file://${__dirname}/externalMedia.html`} - onLoad={() => setIframeLoaded(true)} + onLoad={() => { + setIframeLoaded(true); + setMediaShouldLoad(true); + }} /> )} {!mediaShouldLoad && ( <> - - + + The Tokel team does not own, endorse, host or content moderate anything that is shown in + the dApp. By it's nature, the dApp merely reads the media URL's that are + linked within the meta data of tokens that are created on the Tokel public blockchain. + Content moderation issues should be addressed with the token creator, owner, or through + the web host that stores the media itself. + + + By accepting this disclaimer, you are accepting that you have personally verified the + source of the image and are happy for it to be displayed, knowing that there are no + content moderators and you're taking all responsibility for viewing the media and + any risks associated with that. You are accepting that anybody that participates in + creating and/or shipping this open source software holds no liability for what is shown, + and that the decision to proceed is completely voluntary and at your own risk. + + + setMediaShouldLoad(true)}> + View once + + addTokenToWhiteList()}> + View and never ask again + + )} diff --git a/src/vars/defines.ts b/src/vars/defines.ts index f205aa85..6a6868b6 100644 --- a/src/vars/defines.ts +++ b/src/vars/defines.ts @@ -26,6 +26,8 @@ export const IS_DEV = process.env.NODE_ENV === 'development' || process.env.NODE export const IS_PROD = process.env.NODE_ENV === 'production'; export const SATOSHIS = 100000000; +export const TOKEN_WHITE_LIST_LOCATION = 'token_white_list'; + export enum NetworkType { TOKEL = 'TOKEL', TKLTEST = 'TKLTEST2', From 9b9da2729dd8a603747e1553681255bdca64bae9 Mon Sep 17 00:00:00 2001 From: rannyeribaptist Date: Tue, 12 Jul 2022 16:19:03 -0300 Subject: [PATCH 3/5] Added a visual warning sign to the disclaimer text and Hide image button --- src/components/_General/TokenMediaDisplay.tsx | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/src/components/_General/TokenMediaDisplay.tsx b/src/components/_General/TokenMediaDisplay.tsx index 200d5537..ccf582d1 100644 --- a/src/components/_General/TokenMediaDisplay.tsx +++ b/src/components/_General/TokenMediaDisplay.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import styled from '@emotion/styled'; import { ipcRenderer } from 'electron'; +import warning from 'assets/warningIcon.svg'; import { Responsive, extractIPFSHash } from 'util/helpers'; import { V } from 'util/theming'; import { @@ -37,15 +38,17 @@ const TokenMediaIframe = styled.iframe` `; const ButtonWrapper = styled.div` + width: 100%; display: flex; - justify-content: space-between; + justify-content: space-around; margin-top: 25px; `; -const DisclaimerText = styled.p` +const DisclaimerText = styled.div` text-align: justify; text-align-last: center; font-size: 0.9rem; + margin-top: 25px; `; interface TokenMediaDisplayProps { @@ -142,25 +145,44 @@ const TokenMediaDisplay: React.FC = ({ url }) => { setMediaShouldLoad(true); } + function removeTokenFromWhiteList() { + localStorage.removeItem(`${TOKEN_WHITE_LIST_LOCATION}/${tokenAddress}`); + setMediaShouldLoad(false); + setIframeLoaded(false); + } + return ( <> {mediaShouldLoad && ( - - - { - setIframeLoaded(true); - setMediaShouldLoad(true); - }} - /> - - + <> + + + { + setIframeLoaded(true); + setMediaShouldLoad(true); + }} + /> + + + + removeTokenFromWhiteList()} + > + Hide Image + + + )} {!mediaShouldLoad && ( - <> +
+ warning + The Tokel team does not own, endorse, host or content moderate anything that is shown in the dApp. By it's nature, the dApp merely reads the media URL's that are @@ -176,6 +198,7 @@ const TokenMediaDisplay: React.FC = ({ url }) => { creating and/or shipping this open source software holds no liability for what is shown, and that the decision to proceed is completely voluntary and at your own risk. + setMediaShouldLoad(true)}> View once @@ -184,7 +207,7 @@ const TokenMediaDisplay: React.FC = ({ url }) => { View and never ask again - +
)} ); From 685f19dbbc3d11a40526b8c15fc4166dca1461ba Mon Sep 17 00:00:00 2001 From: rannyeribaptist Date: Tue, 19 Jul 2022 22:37:16 -0300 Subject: [PATCH 4/5] improvements suggested by code review --- src/components/_General/TokenMediaDisplay.tsx | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/src/components/_General/TokenMediaDisplay.tsx b/src/components/_General/TokenMediaDisplay.tsx index ccf582d1..895913d8 100644 --- a/src/components/_General/TokenMediaDisplay.tsx +++ b/src/components/_General/TokenMediaDisplay.tsx @@ -48,7 +48,6 @@ const DisclaimerText = styled.div` text-align: justify; text-align-last: center; font-size: 0.9rem; - margin-top: 25px; `; interface TokenMediaDisplayProps { @@ -61,6 +60,7 @@ const TokenMediaDisplay: React.FC = ({ url }) => { const [iframeHeight, setIframeHeight] = useState('unset'); const [mediaUrl, setMediaUrl] = useState(null); const [mediaShouldLoad, setMediaShouldLoad] = useState(false); + const [readMore, setReadMore] = useState(false); const ipfsId = useMemo(() => extractIPFSHash(url), [url]); const tokenAddress = ipfsId || url; @@ -71,6 +71,7 @@ const TokenMediaDisplay: React.FC = ({ url }) => { setMediaUrl(null); setIframeLoaded(false); setMediaShouldLoad(false); + setReadMore(false); iframeRef.current?.contentWindow.postMessage({ mediaUrl: '', width: 0 }); }, [url]); @@ -182,31 +183,51 @@ const TokenMediaDisplay: React.FC = ({ url }) => { {!mediaShouldLoad && (
warning - - - The Tokel team does not own, endorse, host or content moderate anything that is shown in - the dApp. By it's nature, the dApp merely reads the media URL's that are - linked within the meta data of tokens that are created on the Tokel public blockchain. - Content moderation issues should be addressed with the token creator, owner, or through - the web host that stores the media itself. - - - By accepting this disclaimer, you are accepting that you have personally verified the - source of the image and are happy for it to be displayed, knowing that there are no - content moderators and you're taking all responsibility for viewing the media and - any risks associated with that. You are accepting that anybody that participates in - creating and/or shipping this open source software holds no liability for what is shown, - and that the decision to proceed is completely voluntary and at your own risk. - - - - setMediaShouldLoad(true)}> - View once - - addTokenToWhiteList()}> - View and never ask again - - +

Disclaimer

+ + {!readMore && ( + <> + + The Tokel team does not own, endorse, host or content moderate anything that is + shown in the dApp. By it's nature, the dApp merely reads... + +
+ setReadMore(true)}> + Read More + + + )} + + {readMore && ( + <> + + The Tokel team does not own, endorse, host or content moderate anything that is + shown in the dApp. By it's nature, the dApp merely reads the media URL's + that are linked within the meta data of tokens that are created on the Tokel public + blockchain. Content moderation issues should be addressed with the token creator, + owner, or through the web host that stores the media itself. + +
+ + By accepting this disclaimer, you are accepting that you have personally verified + the source of the image and are happy for it to be displayed, knowing that there are + no content moderators and you're taking all responsibility for viewing the + media and any risks associated with that. You are accepting that anybody that + participates in creating and/or shipping this open source software holds no + liability for what is shown, and that the decision to proceed is completely + voluntary and at your own risk. + + + + setMediaShouldLoad(true)}> + View once + + addTokenToWhiteList()}> + View and never ask again + + + + )}
)} From af1b1b32d1f566cb18c7d7e3c4e522069e6f4f8c Mon Sep 17 00:00:00 2001 From: rannyeribaptist Date: Mon, 25 Jul 2022 13:47:37 -0300 Subject: [PATCH 5/5] Updated the disclaimer in TokenMediaDisplay --- src/components/_General/TokenMediaDisplay.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/_General/TokenMediaDisplay.tsx b/src/components/_General/TokenMediaDisplay.tsx index 895913d8..a7911230 100644 --- a/src/components/_General/TokenMediaDisplay.tsx +++ b/src/components/_General/TokenMediaDisplay.tsx @@ -3,7 +3,6 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import styled from '@emotion/styled'; import { ipcRenderer } from 'electron'; -import warning from 'assets/warningIcon.svg'; import { Responsive, extractIPFSHash } from 'util/helpers'; import { V } from 'util/theming'; import { @@ -14,6 +13,7 @@ import { } from 'vars/defines'; import { ButtonSmall } from 'components/_General/buttons'; +import FriendlyWarning from 'components/_General/WarningFriendly'; const MediaContent = styled.div` overflow-y: auto; @@ -182,8 +182,9 @@ const TokenMediaDisplay: React.FC = ({ url }) => { )} {!mediaShouldLoad && (
- warning -

Disclaimer

+ + +
{!readMore && ( <>