add embeds: youtube, odysee, bitchute, streamable

This commit is contained in:
plebeius.eth
2023-07-07 17:48:24 +02:00
parent 97fb0de9bf
commit 106c865b82
9 changed files with 1076 additions and 336 deletions
+4 -2
View File
@@ -229,8 +229,10 @@ const ReplyModal = ({ isOpen, closeModal }) => {
}, [selectedParentCid, anonymousMode, account]);
useEffect(() => {
updateSigner();
}, [updateSigner]);
if (anonymousMode) {
updateSigner();
}
}, [updateSigner, anonymousMode]);
useEffect(() => {
+11 -1
View File
@@ -2016,6 +2016,16 @@ export const BoardForm = styled.div`
}
video {
width: 100%;
height: auto;
}
iframe {
width: 100%;
height: auto;
}
#video-thumbnail-mobile {
width: 100px;
}
@@ -3804,7 +3814,7 @@ export const BoardForm = styled.div`
color: #707070;
font-weight: 700;
background-color: rgb(27,28,30);
border: 1px solid #282A2E;
border: 1px solid #2D2F33;
background-image: url(assets/buttonfade-dark.png);
background-repeat: repeat-x;
text-decoration: none;
@@ -1193,7 +1193,13 @@ export const BoardForm = styled.div`
}
video {
width: 100px;
width: 100%;
height: auto;
}
iframe {
width: 100%;
height: auto;
}
img {
@@ -2932,7 +2938,7 @@ export const BoardForm = styled.div`
color: #707070;
font-weight: 700;
background-color: rgb(27,28,30);
border: 1px solid #282A2E;
border: 1px solid #2D2F33;
background-image: url(assets/buttonfade-dark.png);
background-repeat: repeat-x;
text-decoration: none;
+208 -81
View File
@@ -102,6 +102,8 @@ const All = () => {
const [moderatorPermissions, setModeratorPermissions] = useState({});
const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({});
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
const setSelectedThreadCid = (cid) => {
selectedThreadCidRef.current = cid;
@@ -117,6 +119,20 @@ const All = () => {
const stateString = useFeedStateString(subplebbits);
const handleThumbnailClick = (index, isMobile=false) => {
if (isMobile) {
setIsMobileThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
} else {
setIsThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
}
};
useEffect(() => {
let permissions = {};
@@ -618,56 +634,110 @@ const All = () => {
<hr key={`hr-${index}`} />
<div key={`pi-${index}`} className="post-info">
{commentMediaInfo?.url ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type})
</div>
{commentMediaInfo?.type === "webpage" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{thread.thumbnailUrl ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
{isThumbnailClicked[index] ? (
<span>
-[
<span className='reply-link'
style={{textDecoration: 'underline', cursor: 'pointer'}}
onClick={() => {handleThumbnailClick(index)}}>Close</span>
]
</span>
) : null}
</div>
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-${index}`}
className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{(isThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<iframe
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.embedUrl}
width={commentMediaInfo.thumbnail ? "560" : "250"}
height="315"
style={{border: "none"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
) : (
<img
key={`fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
</span>
</div>
)}
{commentMediaInfo?.type === "webpage" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{thread.thumbnailUrl ? (
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<div key={`enlarge-${index}`} className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{isThumbnailClicked[index] ? (
<video
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.url}
controls
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<div key={`enlarge-${index}`} className="img-container">
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<span key={`fta-${index}`} className="file-thumb">
<video controls width="" key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${index}`} className="file-thumb">
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
</div>
) : null}
) : null}
</div>
) : null}
<span key={`nb-${index}`} className="name-block">
{thread.title ? (
thread.title.length > 75 ?
@@ -1562,51 +1632,108 @@ const All = () => {
</span>
</div>
{thread.link ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{thread.thumbnailUrl ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-fta-${index}`} className="file-thumb-mobile">
{(isMobileThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<div style={{width: "92vw"}}>
<iframe
key={`mob-fti-${index}`}
src={commentMediaInfo.embedUrl}
style={{border: "none", height: "250px"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
</div>
) : (
<img
key={`mob-fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
</div>
)}
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{thread.thumbnailUrl ? (
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
style={{ pointerEvents: "none" }}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{isMobileThumbnailClicked[index] ? (
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
controls
style={{ cursor: 'pointer' }}
onError={(e) => e.target.src = fallbackImgUrl} />
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
id="video-thumbnail-mobile"
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : null}
{thread.content ? (
thread.content?.length > 500 ?
<Fragment key={`fragment12-${index}`}>
+142 -11
View File
@@ -128,6 +128,8 @@ const Board = () => {
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({});
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
const setSelectedThreadCid = (cid) => { selectedThreadCidRef.current = cid;}
@@ -147,10 +149,26 @@ const Board = () => {
}, [account?.author.address, subplebbit.roles]);
const handleThumbnailClick = (index, isMobile=false) => {
if (isMobile) {
setIsMobileThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
} else {
setIsThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
}
};
const handleOptionClick = () => {
setOpenMenuCid(null);
};
const handleOutsideClick = useCallback((e) => {
if (openMenuCid !== null && !postMenuCatalogRef.current.contains(e.target)) {
setOpenMenuCid(null);
@@ -439,8 +457,10 @@ const Board = () => {
}, [selectedThreadCidRef, anonymousMode, account]);
useEffect(() => {
updateSigner();
}, [updateSigner]);
if (anonymousMode) {
updateSigner();
}
}, [updateSigner, anonymousMode]);
@@ -1268,8 +1288,44 @@ const Board = () => {
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type})
}</a>&nbsp;({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
{isThumbnailClicked[index] ? (
<span>
-[
<span className='reply-link'
style={{textDecoration: 'underline', cursor: 'pointer'}}
onClick={() => {handleThumbnailClick(index)}}>Close</span>
]
</span>
) : null}
</div>
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-${index}`}
className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{(isThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<iframe
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.embedUrl}
width={commentMediaInfo.thumbnail ? "560" : "250"}
height="315"
style={{border: "none"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
) : (
<img
key={`fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
</span>
</div>
)}
{commentMediaInfo?.type === "webpage" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
@@ -1295,11 +1351,29 @@ const Board = () => {
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<div key={`enlarge-${index}`} className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
<video controls width="" key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
{isThumbnailClicked[index] ? (
<video
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.url}
controls
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
</span>
</div>
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${index}`} className="file-thumb">
@@ -2191,6 +2265,41 @@ const Board = () => {
</div>
{thread.link ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-fta-${index}`} className="file-thumb-mobile">
{(isMobileThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<div style={{width: "92vw"}}>
<iframe
key={`mob-fti-${index}`}
src={commentMediaInfo.embedUrl}
style={{border: "none", height: "250px"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
</div>
) : (
<img
key={`mob-fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
</div>
)}
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
@@ -2218,11 +2327,33 @@ const Board = () => {
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
style={{ pointerEvents: "none" }}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
{isMobileThumbnailClicked[index] ? (
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
controls
style={{ cursor: 'pointer' }}
onError={(e) => e.target.src = fallbackImgUrl} />
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
id="video-thumbnail-mobile"
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
+228 -65
View File
@@ -12,6 +12,7 @@ import PostLoader from '../PostLoader';
import SettingsModal from '../modals/SettingsModal';
import getCommentMediaInfo from '../../utils/getCommentMediaInfo';
import getDate from '../../utils/getDate';
import handleImageClick from '../../utils/handleImageClick';
import handleQuoteClick from '../../utils/handleQuoteClick';
import handleStyleChange from '../../utils/handleStyleChange';
import useError from '../../hooks/useError';
@@ -35,6 +36,23 @@ const Pending = () => {
const account = useAccount();
const comment = useAccountComment({commentIndex: index});
const [, setNewErrorMessage] = useError();
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
const handleThumbnailClick = (index, isMobile=false) => {
if (isMobile) {
setIsMobileThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
} else {
setIsThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
}
};
useEffect(() => {
setSelectedAddress(comment?.subplebbitAddress);
@@ -138,28 +156,29 @@ const Pending = () => {
]
</span>
<div id="board-nav-mobile" style={{ top: visible ? 0 : '-23px' }}>
<div className="board-select">
<strong>Board</strong>
&nbsp;
<select id="board-select-mobile" value={selectedAddress} onChange={handleSelectChange}>
<option value="all">All</option>
<option value="subscriptions">Subscriptions</option>
{defaultSubplebbits.map(subplebbit => (
<option key={`option-${subplebbit.address}`} value={subplebbit.address}
>{subplebbit.title ? subplebbit.title : subplebbit.address}</option>
))}
</select>
<span style={{cursor: 'pointer'}} onClick={
<div className="nav-container">
<div className="board-select">
<strong>Board</strong>
&nbsp;
<select id="board-select-mobile" value={selectedAddress} onChange={handleSelectChange}>
<option value="all">All</option>
<option value="subscriptions">Subscriptions</option>
{defaultSubplebbits.map(subplebbit => (
<option key={`option-${subplebbit.address}`} value={subplebbit.address}
>{subplebbit.title ? subplebbit.title : subplebbit.address}</option>
))}
</select> 
<span id="button-span" style={{cursor: 'pointer'}} onClick={
() => alert(
'To create a board, first you have to run a full node.\nYou can run a full node by simply browsing with the plebbit desktop app. After you download it, open it, wait for it loading, then click on "Home" in the top left, then "Create Community".\n\nAfter you create the community, you can go back to plebchan at any time to see it as a board by pasting its address (begins with p/12D3KooW...) in the search bar, which is in the Home.\n\nNote:\n\n- Your community will be online for as long as you leave the app open, because it functions like a server for the community.\n- The longer you leave the app open, the more data you are seeding to the protocol, which helps performance for everybody.\n - All the data in the plebbit protocol is just text, which is extremely lightweight. All media is generated by links, which is text, embedded by the clients.\n\nDownload the plebbit app here: https://github.com/plebbit/plebbit-react/releases\n\nYou can also use a CLI: https://github.com/plebbit/plebbit-cli\n\nRunning boards in the plebchan app is a planned feature.\n\n'
)
}>Create Board</span>
</div>
<div className="page-jump">
<Link to={`/profile/c/${index}/settings`} onClick={() => setIsSettingsOpen(true)}>Settings</Link>
&nbsp;
<Link to="/" onClick={() => handleStyleChange({target: {value: "Yotsuba"}}
)}>Home</Link>
}>Create Board</span>
</div>
<div className="page-jump">
<Link to={`/p/${selectedAddress}/settings`} onClick={() => setIsSettingsOpen(true)}>Settings</Link>
&nbsp;
<Link to="/" onClick={() => {handleStyleChange({target: {value: "Yotsuba"}}); window.scrollTo(0, 0);}}>Home</Link>
</div>
</div>
</div>
<div id="separator-mobile">&nbsp;</div>
@@ -228,35 +247,107 @@ const Pending = () => {
<div className="op-container">
<div className="post op">
<div className="post-info">
{commentMediaInfo?.url ? (
<div key={`f-${"pending"}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${"pending"}`} className="file-text">
{commentMediaInfo?.url ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${"pending"}`} href={commentMediaInfo.url}
target="_blank" rel="noreferrer">{
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type})
}</a>&nbsp;({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
{isThumbnailClicked[index] ? (
<span>
-[
<span className='reply-link'
style={{textDecoration: 'underline', cursor: 'pointer'}}
onClick={() => {handleThumbnailClick(index)}}>Close</span>
]
</span>
) : null}
</div>
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-${index}`}
className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{(isThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<iframe
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.embedUrl}
width={commentMediaInfo.thumbnail ? "560" : "250"}
height="315"
style={{border: "none"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
) : (
<img
key={`fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
</span>
</div>
)}
{commentMediaInfo?.type === "webpage" ? (
<span key={`fta-${"pending"}`} className="file-thumb">
<img key={`fti-${"pending"}`} src={comment.thumbnailUrl} alt="thumbnail" onError={(e) => e.target.src = fallbackImgUrl} />
</span>
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{comment.thumbnailUrl ? (
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<span key={`fta-${"pending"}`} className="file-thumb">
<img key={`fti-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
</span>
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<span key={`fta-${"pending"}`} className="file-thumb">
<video controls key={`fti-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`enlarge-${index}`} className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{isThumbnailClicked[index] ? (
<video
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.url}
controls
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
</span>
</div>
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${"pending"}`} className="file-thumb">
<audio controls key={`fti-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
<span key={`fta-${index}`} className="file-thumb">
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
</div>
@@ -360,37 +451,109 @@ const Pending = () => {
<span key="pending-mob" style={{color: 'red', fontWeight: '700'}}>Pending</span>
</span>
</div>
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`mob-f-${"pending"}`} className="file-mobile">
<span key={`mob-ft${"pending"}`} className="file-thumb-mobile">
<img key={`mob-img-${"pending"}`} src={comment.thumbnailUrl} alt="thumbnail" onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${"pending"}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
{comment.link ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-fta-${index}`} className="file-thumb-mobile">
{(isMobileThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<div style={{width: "92vw"}}>
<iframe
key={`mob-fti-${index}`}
src={commentMediaInfo.embedUrl}
style={{border: "none", height: "250px"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
</div>
) : (
<img
key={`mob-fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
</div>
)}
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
{comment.thumbnailUrl ? (
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
{isMobileThumbnailClicked[index] ? (
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
controls
style={{ cursor: 'pointer' }}
onError={(e) => e.target.src = fallbackImgUrl} />
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
id="video-thumbnail-mobile"
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`mob-f-${"pending"}`} className="file-mobile">
<span key={`mob-ft${"pending"}`} className="file-thumb-mobile">
<img key={`mob-img-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${"pending"}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<div key={`mob-f-${"pending"}`} className="file-mobile">
<span key={`mob-ft${"pending"}`} className="file-thumb-mobile">
<video controls key={`mob-img-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${"pending"}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
) : commentMediaInfo.type === "audio" ? (
<div key={`mob-f-${"pending"}`} className="file-mobile">
<span key={`mob-ft${"pending"}`} className="file-thumb-mobile">
<audio controls key={`mob-img-${"pending"}`} src={commentMediaInfo.url} alt={commentMediaInfo.type} onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${"pending"}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
) : null
) : null}
) : null}
<blockquote key={`mob-bq-${"pending"}`} className="post-message-mobile">
{comment.content ? (
<>
+209 -81
View File
@@ -102,6 +102,8 @@ const Subscriptions = () => {
const [moderatorPermissions, setModeratorPermissions] = useState({});
const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({});
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
const setSelectedThreadCid = (cid) => {
selectedThreadCidRef.current = cid;
@@ -116,6 +118,21 @@ const Subscriptions = () => {
const stateString = useFeedStateString(subplebbits);
const handleThumbnailClick = (index, isMobile=false) => {
if (isMobile) {
setIsMobileThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
} else {
setIsThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
}
};
useEffect(() => {
let permissions = {};
@@ -628,56 +645,110 @@ const Subscriptions = () => {
<hr key={`hr-${index}`} />
<div key={`pi-${index}`} className="post-info">
{commentMediaInfo?.url ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type})
</div>
{commentMediaInfo?.type === "webpage" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{thread.thumbnailUrl ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
{isThumbnailClicked[index] ? (
<span>
-[
<span className='reply-link'
style={{textDecoration: 'underline', cursor: 'pointer'}}
onClick={() => {handleThumbnailClick(index)}}>Close</span>
]
</span>
) : null}
</div>
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-${index}`}
className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{(isThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<iframe
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.embedUrl}
width={commentMediaInfo.thumbnail ? "560" : "250"}
height="315"
style={{border: "none"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
) : (
<img
key={`fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
</span>
</div>
)}
{commentMediaInfo?.type === "webpage" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{thread.thumbnailUrl ? (
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<div key={`enlarge-${index}`} className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{isThumbnailClicked[index] ? (
<video
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.url}
controls
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<div key={`enlarge-${index}`} className="img-container">
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<span key={`fta-${index}`} className="file-thumb">
<video controls width="" key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${index}`} className="file-thumb">
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
</div>
) : null}
) : null}
</div>
) : null}
<span key={`nb-${index}`} className="name-block">
{thread.title ? (
thread.title.length > 75 ?
@@ -1572,51 +1643,108 @@ const Subscriptions = () => {
</span>
</div>
{thread.link ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{thread.thumbnailUrl ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-fta-${index}`} className="file-thumb-mobile">
{(isMobileThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<div style={{width: "92vw"}}>
<iframe
key={`mob-fti-${index}`}
src={commentMediaInfo.embedUrl}
style={{border: "none", height: "250px"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
</div>
) : (
<img
key={`mob-fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
</div>
)}
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{thread.thumbnailUrl ? (
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
style={{ pointerEvents: "none" }}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
{isMobileThumbnailClicked[index] ? (
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
controls
style={{ cursor: 'pointer' }}
onError={(e) => e.target.src = fallbackImgUrl} />
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
id="video-thumbnail-mobile"
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${thread.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : null}
{thread.content ? (
thread.content?.length > 500 ?
<Fragment key={`fragment12-${index}`}>
+195 -68
View File
@@ -111,6 +111,8 @@ const Thread = () => {
const [postOnHoverHeight, setPostOnHoverHeight] = useState(0);
const [executeAnonMode, setExecuteAnonMode] = useState(false);
const [cidTracker, setCidTracker] = useState({});
const [isThumbnailClicked, setIsThumbnailClicked] = useState({});
const [isMobileThumbnailClicked, setIsMobileThumbnailClicked] = useState({});
useAnonMode(selectedThread, anonymousMode && executeAnonMode);
@@ -126,6 +128,21 @@ const Thread = () => {
const fallbackImgUrl = "assets/filedeleted-res.gif";
const handleThumbnailClick = (index, isMobile=false) => {
if (isMobile) {
setIsMobileThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
} else {
setIsThumbnailClicked(prevState => ({
...prevState,
[index]: !prevState[index],
}));
}
};
useEffect(() => {
if (subplebbit.roles !== undefined) {
const role = subplebbit.roles[account?.author?.address]?.role;
@@ -397,8 +414,10 @@ const Thread = () => {
}, [selectedThread, anonymousMode, account]);
useEffect(() => {
updateSigner();
}, [updateSigner]);
if (anonymousMode) {
updateSigner();
}
}, [updateSigner, anonymousMode]);
useEffect(() => {
@@ -794,52 +813,106 @@ const Thread = () => {
<div className="op-container">
<div className="post op op-desktop">
<div className="post-info">
{commentMediaInfo?.url ? (
<div key={`f-${comment.cid}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${comment.cid}`} className="file-text">
{commentMediaInfo?.url ? (
<div key={`f-${index}`} className="file" style={{marginBottom: "5px"}}>
<div key={`ft-${index}`} className="file-text">
Link:&nbsp;
<a key={`fa-${comment.cid}`} href={commentMediaInfo.url}
target="_blank" rel="noreferrer">{
<a key={`fa-${index}`} href={commentMediaInfo.url} target="_blank"
rel="noopener noreferrer">{
commentMediaInfo?.url.length > 30 ?
commentMediaInfo?.url.slice(0, 30) + "(...)" :
commentMediaInfo?.url
}</a>&nbsp;({commentMediaInfo?.type})
}</a>&nbsp;({commentMediaInfo?.type === "iframe" ? "video" : commentMediaInfo?.type})
{isThumbnailClicked[index] ? (
<span>
-[
<span className='reply-link'
style={{textDecoration: 'underline', cursor: 'pointer'}}
onClick={() => {handleThumbnailClick(index)}}>Close</span>
]
</span>
) : null}
</div>
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-${index}`}
className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{(isThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<iframe
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.embedUrl}
width={commentMediaInfo.thumbnail ? "560" : "250"}
height="315"
style={{border: "none"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
) : (
<img
key={`fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
</span>
</div>
)}
{commentMediaInfo?.type === "webpage" ? (
<div key="enlarge" className="img-container">
<span key={`fta-${comment.cid}`} className="file-thumb">
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
{comment.thumbnailUrl ? (
<img key={`fti-${comment.cid}`}
<img key={`fti-${index}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
</span>
</div>
) : null}
{commentMediaInfo?.type === "image" ? (
<div key="enlarge" className="img-container">
<span key={`fta-${comment.cid}`} className="file-thumb">
<img key={`fti-${comment.cid}`}
<div key={`enlarge-${index}`} className="img-container">
<span key={`fta-${index}`} className="file-thumb">
<img key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
</div>
) : null}
{commentMediaInfo?.type === "video" ? (
<span key={`fta-${comment.cid}`} className="file-thumb">
<video controls key={`fti-${comment.cid}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`enlarge-${index}`} className={`img-container ${isThumbnailClicked[index] ? 'expanded-container' : ''}`}>
<span key={`fta-${index}`} className="file-thumb">
{isThumbnailClicked[index] ? (
<video
className='enlarged'
key={`fti-${index}`}
src={commentMediaInfo.url}
controls
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
</span>
</div>
) : null}
{commentMediaInfo?.type === "audio" ? (
<span key={`fta-${comment.cid}`} className="file-thumb">
<audio controls key={`fti-${comment.cid}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
<span key={`fta-${index}`} className="file-thumb">
<audio controls key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
</span>
) : null}
@@ -1559,54 +1632,108 @@ const Thread = () => {
}}}>{comment.shortCid}</Link>
</span>
</div>
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`mob-f-${comment.cid}`} className="file-mobile">
<div key="enlarge-reply-mob" className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
{comment.thumbnailUrl ? (
<img key={`mob-img-${comment.cid}`}
src={commentMediaInfo.thumbnail} alt={commentMediaInfo.type}
{comment.link ? (
<div key={`mob-f-${index}`} className="file-mobile">
{commentMediaInfo?.type === 'iframe' && (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-fta-${index}`} className="file-thumb-mobile">
{(isMobileThumbnailClicked[index] || !commentMediaInfo.thumbnail) && commentMediaInfo.embedUrl ? (
<div style={{width: "92vw"}}>
<iframe
key={`mob-fti-${index}`}
src={commentMediaInfo.embedUrl}
style={{border: "none", height: "250px"}}
title="Embedded content"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen />
</div>
) : (
<img
key={`mob-fti-${index}`}
src={commentMediaInfo.thumbnail}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
</div>
)}
{commentMediaInfo?.url ? (
commentMediaInfo.type === "webpage" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
{comment.thumbnailUrl ? (
<img key={`mob-img-${index}`}
src={commentMediaInfo.thumbnail} alt="thumbnail"
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`enlarge-mob-${index}`} className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
) : null}
<div key={`mob-fi-${comment.cid}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
</div>
) : commentMediaInfo.type === "image" ? (
<div key={`mob-f-${comment.cid}`} className="file-mobile">
<div key="enlarge-reply-mob" className="img-container">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<img key={`mob-img-${comment.cid}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onClick={handleImageClick}
style={{cursor: "pointer"}}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${comment.cid}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
</div>
) : commentMediaInfo.type === "video" ? (
<div key={`mob-f-${comment.cid}`} className="file-mobile">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<video controls key={`mob-img-${comment.cid}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${comment.cid}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
) : commentMediaInfo.type === "audio" ? (
<div key={`mob-f-${comment.cid}`} className="file-mobile">
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<audio controls key={`mob-img-${comment.cid}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${comment.cid}`} className="file-info-mobile">{commentMediaInfo.type}</div>
</span>
</div>
) : null
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
</div>
) : commentMediaInfo.type === "video" ? (
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
{isMobileThumbnailClicked[index] ? (
<video key={`fti-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
controls
style={{ cursor: 'pointer' }}
onError={(e) => e.target.src = fallbackImgUrl} />
) : (
<video
key={`fti-${index}`}
src={commentMediaInfo.url}
alt="thumbnail"
onClick={() => {handleThumbnailClick(index, true)}}
style={{cursor: "pointer"}}
id="video-thumbnail-mobile"
onError={(e) => e.target.src = fallbackImgUrl}
/>
)}
{commentMediaInfo?.type === "video" || "iframe" ? (
isMobileThumbnailClicked[index] ? (
<div style={{textAlign: "center", marginTop: "15px", marginBottom: "15px"}}>
<span className='button-mobile' style={{float: "none", cursor: "pointer"}}
onClick={() => {handleThumbnailClick(index, true)}}
>Close</span>
</div>
) : (
<div key={`mob-fi-${index}`} className="file-info-mobile">video</div>
)) : <div key={`mob-fi-${index}`} className="file-info-mobile">video</div>}
</span>
) : commentMediaInfo.type === "audio" ? (
<span key={`mob-ft${comment.cid}`} className="file-thumb-mobile">
<audio key={`mob-img-${index}`}
src={commentMediaInfo.url} alt={commentMediaInfo.type}
onError={(e) => e.target.src = fallbackImgUrl} />
<div key={`mob-fi-${index}`} className="file-info-mobile">{commentMediaInfo?.type}</div>
</span>
) : null
) : null}
</div>
) : null}
<blockquote key={`mob-bq-${comment.cid}`} className="post-message-mobile">
{comment.content ? (
+71 -25
View File
@@ -7,34 +7,80 @@ const getCommentMediaInfo = (comment) => {
if (comment?.link) {
try {
new URL(comment.link);
const url = new URL(comment.link);
const host = url.hostname;
let embedUrl = null;
if (['youtube.com', 'www.youtube.com', 'youtu.be'].includes(host)) {
const videoId = host === 'youtu.be' ? url.pathname.slice(1) : url.searchParams.get('v');
embedUrl = `https://www.youtube-nocookie.com/embed/${videoId}`;
} else if (host.includes('odysee.com')) {
const pathComponents = url.pathname.split('/');
const channelAndId = pathComponents[1];
const videoAndId = pathComponents[2];
embedUrl = `https://odysee.com/$/embed/${channelAndId}/${videoAndId}`;
// TODO: add support for Rumble, video id is dynamic
// } else if (host.includes('rumble.com')) {
// const regex = /(\/v.+?)-/;
// const match = regex.exec(url.pathname);
// if (match) {
// const videoId = match[1].slice(1);
// embedUrl = `https://rumble.com/embed/${videoId}/?pub=4`;
// }
} else if (host.includes('bitchute.com')) {
const videoId = url.pathname.split('/')[2];
embedUrl = `https://www.bitchute.com/embed/${videoId}/`;
} else if (host.includes('streamable.com')) {
const videoId = url.pathname.split('/')[1];
embedUrl = `https://streamable.com/e/${videoId}?quality=highest`;
// TODO: Add support for Giphy (doesn't have thumbnails, size is variable)
// } else if (host.includes('giphy.com')) {
// const hyphenComponents = url.pathname.split('-');
// const gifId = hyphenComponents[hyphenComponents.length - 1];
// embedUrl = `https://giphy.com/embed/${gifId}`;
}
if (embedUrl) {
return {
url: comment.link,
embedUrl,
type: 'iframe',
thumbnail: comment.thumbnailUrl,
};
}
const mime = extName(url.pathname.replace('/', ''))[0]?.mime;
if (mime?.startsWith('image')) {
return {
url: comment.link,
type: 'image',
};
}
if (mime?.startsWith('video')) {
return {
url: comment.link,
type: 'video',
thumbnail: comment.thumbnailUrl,
};
}
if (mime?.startsWith('audio')) {
return {
url: comment.link,
type: 'audio',
};
}
} catch (error) {
// console.error("Invalid URL:", comment.link);
return;
}
const mime = extName(new URL(comment?.link).pathname.replace('/', ''))[0]?.mime;
if (mime?.startsWith('image')) {
return {
url: comment.link,
type: 'image',
};
}
if (mime?.startsWith('video')) {
return {
url: comment.link,
type: 'video',
};
}
if (mime?.startsWith('audio')) {
return {
url: comment.link,
type: 'audio',
};
}
}
if (comment?.thumbnailUrl && comment?.thumbnailUrl !== comment?.link) {