2023-03-13 14:29:34 +01:00
import React , { useState , useEffect } from 'react' ;
2023-03-06 14:33:31 +01:00
import { Link , useNavigate , useParams , useLocation } from 'react-router-dom' ;
2023-03-13 14:29:34 +01:00
import useBoardStore from '../useBoardStore' ;
2023-03-12 10:27:59 +01:00
import { Container , NavBar , Header , Break , PostForm , PostFormTable , BoardForm } from './styles/Board.styled' ;
import { ReplyFormLink , TopBar , BottomBar } from './styles/Thread.styled' ;
import { useComment , useAccountsActions } from '@plebbit/plebbit-react-hooks' ;
2023-02-12 21:20:08 +01:00
import ImageBanner from './ImageBanner' ;
2023-03-12 22:07:15 +01:00
import CaptchaModal from './CaptchaModal' ;
2023-03-17 14:35:03 +01:00
import ReplyModal from './ReplyModal' ;
2023-03-16 14:04:15 +01:00
import SettingsModal from './SettingsModal' ;
2023-02-28 16:34:33 +01:00
import { Tooltip } from 'react-tooltip' ;
2023-03-13 22:15:57 +01:00
import onError from '../utils/onError' ;
2023-03-15 17:34:31 +01:00
import onSuccess from '../utils/onSuccess' ;
2023-03-05 14:15:51 +01:00
import getDate from '../utils/getDate' ;
2023-03-08 09:49:42 +01:00
import renderThreadComments from '../utils/renderThreadComments' ;
2023-02-12 21:20:08 +01:00
2023-03-02 21:51:06 +01:00
2023-02-12 21:20:08 +01:00
const Thread = ({ setBodyStyle }) => {
2023-03-13 14:29:34 +01:00
const {
selectedTitle ,
setSelectedTitle ,
selectedAddress ,
setSelectedAddress ,
selectedThread ,
setSelectedThread ,
selectedStyle ,
setSelectedStyle ,
captchaResponse ,
setCaptchaResponse
} = useBoardStore ( state => state );
2023-02-12 21:20:08 +01:00
const [ defaultSubplebbits , setDefaultSubplebbits ] = useState ([]);
2023-03-06 14:33:31 +01:00
const [ showPostFormLink , setShowPostFormLink ] = useState ( true );
const [ showPostForm , setShowPostForm ] = useState ( false );
2023-03-12 10:27:59 +01:00
const [ name , setName ] = useState ( '' );
const [ subject , setSubject ] = useState ( '' );
const [ commentContent , setCommentContent ] = useState ( '' );
const { publishComment } = useAccountsActions ();
2023-03-12 22:07:15 +01:00
const [ isCaptchaOpen , setIsCaptchaOpen ] = useState ( false );
2023-03-17 14:35:03 +01:00
const [ isReplyOpen , setIsReplyOpen ] = useState ( false );
2023-03-16 14:04:15 +01:00
const [ isSettingsOpen , setIsSettingsOpen ] = useState ( false );
2023-03-12 22:07:15 +01:00
const [ captchaImage , setCaptchaImage ] = useState ( '' );
2023-02-12 21:20:08 +01:00
const navigate = useNavigate ();
2023-03-06 14:33:31 +01:00
const location = useLocation ();
2023-02-24 20:57:51 +01:00
const [ prevScrollPos , setPrevScrollPos ] = useState ( 0 );
const [ visible , setVisible ] = useState ( true );
2023-03-02 21:51:06 +01:00
const comment = useComment ( ` ${ selectedThread } ` );
2023-03-02 18:19:08 +01:00
const { subplebbitAddress , threadCid } = useParams ();
2023-02-20 22:17:04 +01:00
2023-03-02 21:51:06 +01:00
2023-03-08 09:49:42 +01:00
// temporary title from JSON, gets subplebbitAddress and threadCid from URL
2023-03-02 18:19:08 +01:00
useEffect (() => {
setSelectedAddress ( subplebbitAddress );
setSelectedThread ( threadCid );
const selectedSubplebbit = defaultSubplebbits . find (( subplebbit ) => subplebbit . address === subplebbitAddress );
if ( selectedSubplebbit ) {
setSelectedTitle ( selectedSubplebbit . title );
}
}, [ subplebbitAddress , setSelectedAddress , setSelectedTitle , defaultSubplebbits ]);
2023-02-12 21:20:08 +01:00
2023-03-08 09:49:42 +01:00
// fetches default subplebbits from JSON
2023-02-12 21:20:08 +01:00
useEffect (() => {
let didCancel = false ;
fetch (
"https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/subplebbits.json" ,
{ cache : "no-cache" }
)
. then (( res ) => res . json ())
. then ( res => {
if ( ! didCancel ) {
setDefaultSubplebbits ( res );
}
});
return () => {
didCancel = true ;
};
}, []);
2023-03-08 09:49:42 +01:00
// mobile navbar scroll effect
2023-02-24 20:57:51 +01:00
useEffect (() => {
const handleScroll = () => {
const currentScrollPos = window . pageYOffset ;
setVisible ( prevScrollPos > currentScrollPos || currentScrollPos < 10 );
setPrevScrollPos ( currentScrollPos );
};
window . addEventListener ( 'scroll' , handleScroll );
return () => window . removeEventListener ( 'scroll' , handleScroll );
}, [ prevScrollPos , visible ]);
2023-03-06 14:33:31 +01:00
2023-03-16 14:04:15 +01:00
// nested routes handling
2023-03-06 14:33:31 +01:00
useEffect (() => {
const path = location . pathname ;
if ( path . endsWith ( '/post' )) {
setShowPostFormLink ( false );
setShowPostForm ( true );
} else {
setShowPostFormLink ( true );
setShowPostForm ( false );
}
2023-03-16 14:04:15 +01:00
if ( path . endsWith ( '/settings' )) {
setIsSettingsOpen ( true );
} else {
setIsSettingsOpen ( false );
}
2023-03-06 14:33:31 +01:00
}, [ location . pathname ]);
2023-02-24 20:57:51 +01:00
2023-03-08 13:13:55 +01:00
// automatic dark mode without interefering with user's selected style
useEffect (() => {
const darkModeMediaQuery = window . matchMedia ( '(prefers-color-scheme: dark)' );
const isDarkMode = darkModeMediaQuery . matches ;
if ( isDarkMode ) {
setSelectedStyle ( 'Tomorrow' );
setBodyStyle ({
background : '#1d1f21 none' ,
color : '#c5c8c6' ,
fontFamily : 'Arial, Helvetica, sans-serif'
});
2023-03-11 17:27:46 +01:00
localStorage . setItem ( 'selectedStyle' , 'Tomorrow' );
2023-03-08 13:13:55 +01:00
}
const darkModeListener = ( e ) => {
if ( e . matches ) {
setSelectedStyle ( 'Tomorrow' );
setBodyStyle ({
background : '#1d1f21 none' ,
color : '#c5c8c6' ,
fontFamily : 'Arial, Helvetica, sans-serif'
});
2023-03-11 17:27:46 +01:00
localStorage . setItem ( 'selectedStyle' , 'Tomorrow' );
2023-03-08 13:13:55 +01:00
}
};
darkModeMediaQuery . addEventListener ( 'change' , darkModeListener );
return () => {
darkModeMediaQuery . removeEventListener ( 'change' , darkModeListener );
};
}, []);
2023-03-02 21:51:06 +01:00
2023-03-12 10:27:59 +01:00
const onChallengeVerification = ( challengeVerification ) => {
if ( challengeVerification . challengeSuccess === true ) {
2023-03-15 17:34:31 +01:00
onSuccess ( 'challenge success' , { publishedCid : challengeVerification . publication . cid })
2023-03-12 10:27:59 +01:00
}
else if ( challengeVerification . challengeSuccess === false ) {
2023-03-15 17:34:31 +01:00
onError ( 'challenge failed' , { reason : challengeVerification . reason , errors : challengeVerification . errors });
onError ( "Error: You seem to have mistyped the CAPTCHA. Please try again." );
2023-03-12 10:27:59 +01:00
}
}
const onChallenge = async ( challenges , comment ) => {
let challengeAnswers = [];
try {
challengeAnswers = await getChallengeAnswersFromUser ( challenges )
}
catch ( error ) {
2023-03-15 17:34:31 +01:00
onError ( error );
2023-03-12 10:27:59 +01:00
}
if ( challengeAnswers ) {
await comment . publishChallengeAnswers ( challengeAnswers )
}
}
const getChallengeAnswersFromUser = async ( challenges ) => {
return new Promise (( resolve , reject ) => {
const imageString = challenges ? . challenges [ 0 ]. challenge ;
const imageSource = `data:image/png;base64, ${ imageString } ` ;
const challengeImg = new Image ();
challengeImg . src = imageSource ;
challengeImg . onload = () => {
2023-03-12 22:07:15 +01:00
setIsCaptchaOpen ( true );
setCaptchaImage ( imageSource );
2023-03-12 10:27:59 +01:00
const handleKeyDown = ( event ) => {
if ( event . key === 'Enter' ) {
2023-03-12 22:07:15 +01:00
setCaptchaImage ( '' );
resolve ( captchaResponse );
setIsCaptchaOpen ( false );
2023-03-12 10:27:59 +01:00
document . removeEventListener ( 'keydown' , handleKeyDown );
}
};
2023-03-12 22:07:15 +01:00
setCaptchaResponse ( '' );
2023-03-12 10:27:59 +01:00
document . addEventListener ( 'keydown' , handleKeyDown );
};
challengeImg . onerror = () => {
2023-03-15 17:34:31 +01:00
reject ( onError ( 'Could not load challenge image' ));
2023-03-12 10:27:59 +01:00
};
});
};
2023-02-12 21:20:08 +01:00
const handleVoidClick = () => {}
2023-03-08 09:49:42 +01:00
// desktop navbar board select functionality
2023-02-27 15:32:16 +01:00
const handleClickTitle = ( title , address ) => {
2023-02-12 21:20:08 +01:00
setSelectedTitle ( title );
setSelectedAddress ( address );
};
2023-03-08 09:49:42 +01:00
// mobile navbar board select functionality
2023-02-27 18:16:47 +01:00
const handleSelectChange = ( event ) => {
const selected = event . target . value ;
const selectedTitle = defaultSubplebbits . find (( subplebbit ) => subplebbit . address === selected ). title ;
setSelectedTitle ( selectedTitle );
setSelectedAddress ( selected );
navigate ( `/ ${ selected } ` );
}
2023-03-02 21:51:06 +01:00
2023-02-12 21:20:08 +01:00
const handleClickHelp = () => {
2023-03-12 10:27:59 +01:00
alert ( "- Embedding media is optional, posts can be text-only. \n- A CAPTCHA challenge will appear after posting. \n- The CAPTCHA is case-sensitive." );
2023-02-12 21:20:08 +01:00
};
2023-03-02 21:51:06 +01:00
2023-02-12 21:20:08 +01:00
const handleClickForm = () => {
2023-03-06 14:33:31 +01:00
setShowPostFormLink ( false );
setShowPostForm ( true );
2023-03-02 21:51:06 +01:00
navigate ( `/ ${ selectedAddress } /thread/ ${ selectedThread } /post` );
2023-02-12 21:20:08 +01:00
};
2023-03-02 21:51:06 +01:00
const handleClickTop = () => {
window . scrollTo ( 0 , 0 );
}
const handleClickBottom = () => {
window . scrollTo ( 0 , document . body . scrollHeight );
}
2023-03-12 10:27:59 +01:00
const handlePublishComment = async () => {
try {
const pendingComment = await publishComment ({
content : commentContent ,
title : subject ,
subplebbitAddress : selectedAddress ,
onChallengeVerification ,
onChallenge ,
2023-03-13 22:15:57 +01:00
onError : onError ,
2023-03-12 10:27:59 +01:00
});
console . log ( `Comment pending with index: ${ pendingComment . index } ` );
setName ( '' );
setSubject ( '' );
setCommentContent ( '' );
} catch ( error ) {
2023-03-13 22:15:57 +01:00
onError ( error );
2023-03-12 10:27:59 +01:00
}
};
2023-03-08 09:49:42 +01:00
// scroll to post when quote is clicked
function handleQuoteClick ( reply , event ) {
event . preventDefault ();
const cid = reply . cid . slice ( 0 , 8 );
const targetElement = [... document . querySelectorAll ( '.post-reply' )]
. find ( el => el . innerHTML . includes ( cid ));
if ( targetElement ) {
targetElement . scrollIntoView ({ behavior : "instant" });
}
}
2023-03-12 22:07:15 +01:00
const handleCaptchaClose = () => {
setIsCaptchaOpen ( false );
};
2023-03-17 14:35:03 +01:00
const handleReplyClose = () => {
setIsReplyOpen ( false );
};
const handleReplyOpen = () => {
setIsReplyOpen ( true );
};
2023-03-16 14:04:15 +01:00
const handleSettingsClose = () => {
setIsSettingsOpen ( false );
}
const handleSettingsOpen = () => {
setIsSettingsOpen ( true );
}
2023-03-02 21:51:06 +01:00
2023-02-12 21:20:08 +01:00
const handleStyleChange = ( event ) => {
switch ( event . target . value ) {
case "Yotsuba" :
2023-03-11 17:27:46 +01:00
const yotsubaBodyStyle = {
2023-02-16 14:05:48 +01:00
background : "#ffe url(/assets/fade.png) top repeat-x" ,
2023-02-12 21:20:08 +01:00
color : "maroon" ,
fontFamily : "Arial, Helvetica, sans-serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( yotsubaBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Yotsuba" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Yotsuba" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( yotsubaBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-03-08 12:49:44 +01:00
case "Yotsuba-B" :
2023-03-11 17:27:46 +01:00
const yotsubaBBodyStyle = {
2023-02-16 14:05:48 +01:00
background : "#eef2ff url(/assets/fade-blue.png) top center repeat-x" ,
2023-02-12 21:20:08 +01:00
color : "#000" ,
fontFamily : "Arial, Helvetica, sans-serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( yotsubaBBodyStyle );
2023-03-08 12:49:44 +01:00
setSelectedStyle ( "Yotsuba-B" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Yotsuba-B" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( yotsubaBBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-02-12 21:20:08 +01:00
case "Futaba" :
2023-03-11 17:27:46 +01:00
const futabaBodyStyle = {
2023-02-12 21:20:08 +01:00
background : "#ffe" ,
color : "maroon" ,
fontFamily : "times new roman, serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( futabaBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Futaba" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Futaba" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( futabaBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-02-12 21:20:08 +01:00
case "Burichan" :
2023-03-11 17:27:46 +01:00
const burichanBodyStyle = {
2023-02-12 21:20:08 +01:00
background : "#eef2ff" ,
color : "#000" ,
fontFamily : "times new roman, serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( burichanBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Burichan" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Burichan" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( burichanBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-02-12 21:20:08 +01:00
case "Tomorrow" :
2023-03-11 17:27:46 +01:00
const tomorrowBodyStyle = {
2023-02-12 21:20:08 +01:00
background : "#1d1f21 none" ,
color : "#c5c8c6" ,
fontFamily : "Arial, Helvetica, sans-serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( tomorrowBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Tomorrow" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Tomorrow" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( tomorrowBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-02-12 21:20:08 +01:00
case "Photon" :
2023-03-11 17:27:46 +01:00
const photonBodyStyle = {
2023-02-12 21:20:08 +01:00
background : "#eee none" ,
color : "#333" ,
fontFamily : "Arial, Helvetica, sans-serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( photonBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Photon" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Photon" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( photonBodyStyle ));
2023-02-12 21:20:08 +01:00
break ;
2023-03-11 17:27:46 +01:00
2023-02-12 21:20:08 +01:00
default :
2023-03-11 17:27:46 +01:00
const defaultBodyStyle = {
2023-02-16 14:05:48 +01:00
background : "#ffe url(/assets/fade.png) top repeat-x" ,
2023-02-12 21:20:08 +01:00
color : "maroon" ,
fontFamily : "Arial, Helvetica, sans-serif"
2023-03-11 17:27:46 +01:00
};
setBodyStyle ( defaultBodyStyle );
2023-02-12 21:20:08 +01:00
setSelectedStyle ( "Yotsuba" );
2023-03-11 17:27:46 +01:00
localStorage . setItem ( "selectedStyle" , "Yotsuba" );
localStorage . setItem ( "bodyStyle" , JSON . stringify ( defaultBodyStyle ));
2023-02-12 21:20:08 +01:00
}
2023-03-11 17:27:46 +01:00
}
2023-02-21 22:12:12 +01:00
2023-03-06 13:33:46 +01:00
2023-03-02 21:51:06 +01:00
2023-02-12 21:20:08 +01:00
return (
< Container >
2023-03-12 22:07:15 +01:00
< CaptchaModal
isOpen = { isCaptchaOpen }
closeModal = { handleCaptchaClose }
captchaImage = { captchaImage } />
2023-03-17 14:35:03 +01:00
< ReplyModal
selectedStyle = { selectedStyle }
isOpen = { isReplyOpen }
closeModal = { handleReplyClose } />
2023-03-16 14:04:15 +01:00
< SettingsModal
selectedStyle = { selectedStyle }
isOpen = { isSettingsOpen }
closeModal = { handleSettingsClose } />
2023-02-12 21:20:08 +01:00
< NavBar selectedStyle = { selectedStyle }>
<>
{ defaultSubplebbits . map ( subplebbit => (
2023-03-11 12:32:42 +01:00
< span className = "boardList" key = { `span- ${ subplebbit . address } ` }>
2023-02-12 21:20:08 +01:00
[
2023-03-11 12:32:42 +01:00
< Link key = { `a- ${ subplebbit . address } ` }
2023-02-27 15:32:16 +01:00
to = { `/ ${ subplebbit . address } ` }
onClick = {() => handleClickTitle ( subplebbit . title , subplebbit . address )}
2023-02-19 22:08:18 +01:00
>{ subplebbit . title }</ Link >
2023-02-12 21:20:08 +01:00
] & nbsp ;
</ span >
))}
2023-02-23 16:45:29 +01:00
< span className = "nav" >
[
2023-03-16 14:04:15 +01:00
< Link to = { `/ ${ selectedAddress } /thread/ ${ selectedThread } /settings` } onClick = { handleSettingsOpen }> Settings </ Link >
2023-02-23 16:45:29 +01:00
]
[
2023-02-12 21:20:08 +01:00
< Link to = "/" onClick = {() => handleStyleChange ({ target : { value : "Yotsuba" }}
2023-02-23 16:45:29 +01:00
)}> Home </ Link >
]
2023-02-12 21:20:08 +01:00
</ span >
2023-02-24 20:57:51 +01:00
< div id = "board-nav-mobile" style = {{ top : visible ? 0 : '-23px' }}>
2023-02-23 16:45:29 +01:00
< div className = "board-select" >
< strong > Board </ strong >
& nbsp ;
2023-02-27 18:16:47 +01:00
< select id = "board-select-mobile" value = { selectedAddress } onChange = { handleSelectChange }>
2023-02-23 16:45:29 +01:00
{ defaultSubplebbits . map ( subplebbit => (
2023-03-11 12:32:42 +01:00
< option key = { `option- ${ subplebbit . address } ` } value = { subplebbit . address }
2023-02-27 18:16:47 +01:00
>{ subplebbit . title }</ option >
2023-02-27 15:32:16 +01:00
))}
2023-02-23 16:45:29 +01:00
</ select >
</ div >
< div className = "page-jump" >
2023-03-16 14:04:15 +01:00
< Link to = { `/ ${ selectedAddress } /thread/ ${ selectedThread } /settings` } onClick = { handleSettingsOpen }> Settings </ Link >
2023-02-23 16:45:29 +01:00
& nbsp ;
< Link to = "/" onClick = {() => handleStyleChange ({ target : { value : "Yotsuba" }}
)}> Home </ Link >
</ div >
</ div >
< div id = "separator-mobile" > & nbsp ;</ div >
< div id = "separator-mobile" > & nbsp ;</ div >
2023-02-12 21:20:08 +01:00
</>
</ NavBar >
< Header selectedStyle = { selectedStyle }>
<>
< div className = "banner" >
< ImageBanner />
</ div >
<>
< div className = "board-title" >{ selectedTitle }</ div >
< div className = "board-address" > p / { selectedAddress }</ div >
</>
</>
</ Header >
< Break selectedStyle = { selectedStyle } />
< PostForm selectedStyle = { selectedStyle } name = "post" action = "" method = "post" enctype = "multipart/form-data" >
2023-03-06 14:33:31 +01:00
< ReplyFormLink id = "post-form-link" showReplyFormLink = { showPostFormLink } selectedStyle = { selectedStyle } >
2023-02-24 18:13:02 +01:00
< div id = "return-button-mobile" >
< span className = "btn-wrap" >
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } ` }> Return </ Link >
2023-02-24 18:13:02 +01:00
</ span >
</ div >
< div id = "catalog-button-mobile" >
< span className = "btn-wrap" >
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } /catalog` }> Catalog </ Link >
2023-02-24 18:13:02 +01:00
</ span >
</ div >
< div id = "bottom-button-mobile" >
< span className = "btn-wrap" >
< a onClick = { handleClickBottom } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' }> Bottom </ a >
</ span >
</ div >
< div id = "post-form-link-desktop" >
2023-02-12 21:20:08 +01:00
[
2023-02-21 14:49:00 +01:00
< a onClick = { handleClickForm } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' }> Post a Reply </ a >
2023-02-12 21:20:08 +01:00
]
2023-02-24 18:13:02 +01:00
</ div >
< div id = "post-form-link-mobile" >
< span className = "btn-wrap" >
< a onClick = { handleClickForm } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' }> Post a Reply </ a >
</ span >
</ div >
2023-02-12 21:20:08 +01:00
</ ReplyFormLink >
2023-03-12 10:27:59 +01:00
< PostFormTable id = "post-form" showPostForm = { showPostForm } selectedStyle = { selectedStyle } className = "post-form" >
2023-02-12 21:20:08 +01:00
< tbody >
2023-03-12 10:27:59 +01:00
< tr data - type = "Name" >
< td id = "td-name" > Name </ td >
2023-02-12 21:20:08 +01:00
< td >
2023-03-12 10:27:59 +01:00
< input name = "name" type = "text" tabIndex = { 1 } placeholder = "Anonymous" value = { name } onChange = {( event ) => setName ( event . target . value )} />
< input id = "post-button" type = "submit" value = "Post" tabIndex = { 6 } onClick = { handlePublishComment } />
2023-02-12 21:20:08 +01:00
</ td >
</ tr >
< tr data - type = "Comment" >
< td > Comment </ td >
< td >
2023-03-12 10:27:59 +01:00
< textarea name = "com" cols = "48" rows = "4" tabIndex = { 4 } wrap = "soft" value = { commentContent } onChange = {( event ) => setCommentContent ( event . target . value )}></ textarea >
2023-02-12 21:20:08 +01:00
</ td >
</ tr >
< tr data - type = "File" >
< td > Embed File </ td >
< td >
< input name = "embed" type = "text" tabIndex = { 7 } placeholder = "Paste link" />
2023-03-12 10:27:59 +01:00
< button id = "t-help" type = "button" onClick = { handleClickHelp } data - tip = "Help" > ? </ button >
</ td >
</ tr >
2023-02-12 21:20:08 +01:00
</ tbody >
2023-03-12 10:27:59 +01:00
</ PostFormTable >
2023-02-12 21:20:08 +01:00
</ PostForm >
< TopBar selectedStyle = { selectedStyle }>
< hr />
< span className = "style-changer" >
Style :
2023-02-13 12:05:10 +01:00
< select id = "style-selector" onChange = { handleStyleChange } value = { selectedStyle }>
2023-02-12 21:20:08 +01:00
< option value = "Yotsuba" > Yotsuba </ option >
2023-03-08 12:49:44 +01:00
< option value = "Yotsuba-B" > Yotsuba B </ option >
2023-02-12 21:20:08 +01:00
< option value = "Futaba" > Futaba </ option >
< option value = "Burichan" > Burichan </ option >
< option value = "Tomorrow" > Tomorrow </ option >
< option value = "Photon" > Photon </ option >
</ select >
</ span >
2023-02-24 18:13:02 +01:00
< span className = "return-button" id = "return-button-desktop" >
2023-02-13 13:01:10 +01:00
[
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } ` }> Return </ Link >
2023-02-13 13:01:10 +01:00
]
</ span >
2023-02-24 18:13:02 +01:00
< span className = "return-button catalog-button" id = "catalog-button-desktop" >
2023-02-21 22:12:12 +01:00
[
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } /catalog` }> Catalog </ Link >
2023-02-21 22:12:12 +01:00
]
</ span >
2023-02-24 18:13:02 +01:00
< span className = "return-button catalog-button" id = "bottom-button-desktop" >
2023-02-21 22:12:12 +01:00
[
2023-03-07 13:54:14 +01:00
< a onClick = { handleClickBottom } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' } onTouchStart = { handleClickBottom }> Bottom </ a >
2023-02-21 22:12:12 +01:00
]
</ span >
2023-03-18 22:05:46 +01:00
{ /* "loading" indicator while replycount loads */ }
2023-02-21 14:49:00 +01:00
{ comment ? (
2023-03-18 22:05:46 +01:00
comment . replyCount !== undefined ? (
comment . replyCount > 0 ? (
comment . replyCount === 1 ? (
< span className = "reply-stat" >{ comment . replyCount } reply </ span >
) : (
< span className = "reply-stat" >{ comment . replyCount } replies </ span >
)
) : (
< span className = "reply-stat" > No replies yet </ span >
)
2023-02-21 14:49:00 +01:00
) : (
2023-03-18 22:05:46 +01:00
< span className = "reply-stat" > Loading ...</ span >
)
) : (
2023-02-21 14:49:00 +01:00
null
)}
2023-02-12 21:20:08 +01:00
< hr />
</ TopBar >
2023-02-20 22:17:04 +01:00
< BoardForm selectedStyle = { selectedStyle }>
{ comment ? (
<>
< div className = "thread" >
2023-02-27 12:35:23 +01:00
< div className = "op-container" >
2023-02-20 22:17:04 +01:00
< div className = "post op" >
< div className = "post-info" >
2023-03-11 12:32:42 +01:00
< div key = { `f- ${ comment . cid } ` } className = "file" >
< div key = { `ft- ${ comment . cid } ` } className = "file-text" >
2023-02-22 16:31:45 +01:00
File :& nbsp ;
2023-03-11 12:32:42 +01:00
< a key = { `fa- ${ comment . cid } ` } href = { ` ${ comment . link } ` } target = "_blank" > filename . something </ a > & nbsp ;( metadata )
2023-02-22 16:31:45 +01:00
</ div >
2023-03-16 13:55:39 +01:00
< Link to = "" key = { `fta- ${ comment . cid } ` } onClick = { handleVoidClick } className = "file-thumb" >
2023-03-11 12:32:42 +01:00
< img key = { `fti- ${ comment . cid } ` } src = "/assets/plebchan-psycho.png" alt = "filename.something" />
2023-03-07 13:54:14 +01:00
</ Link >
2023-02-22 16:31:45 +01:00
</ div >
2023-02-20 22:17:04 +01:00
< span className = "name-block" >
2023-03-01 17:55:35 +01:00
{ comment . title ? (
comment . title . length > 75 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-tm- ${ comment . cid } ` } id = "tt-title-mobile" className = "tooltip" />
< span key = { `q- ${ comment . cid } ` } className = "title"
2023-03-01 17:55:35 +01:00
data - tooltip - id = "tt-title-mobile"
data - tooltip - content = { comment . title }
data - tooltip - place = "top" >
{ comment . title . slice ( 0 , 75 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `q- ${ comment . cid } ` } className = "title" >
2023-03-01 17:55:35 +01:00
{ comment . title }
</ span >)
: null }
2023-02-22 11:22:36 +01:00
& nbsp ;
2023-03-01 17:55:35 +01:00
{ comment . author . displayName
? comment . author . displayName . length > 20
? <>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-nm- ${ comment . cid } ` } id = "tt-name-mobile" className = "tooltip" />
< span key = { `n- ${ comment . cid } ` } className = "name"
2023-03-01 17:55:35 +01:00
data - tooltip - id = "tt-name-mobile"
data - tooltip - content = { comment . author . displayName }
data - tooltip - place = "top" >
{ comment . author . displayName . slice ( 0 , 20 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `n- ${ comment . cid } ` } className = "name" >
2023-03-01 17:55:35 +01:00
{ comment . author . displayName }</ span >
2023-03-11 12:32:42 +01:00
: < span key = { `n- ${ comment . cid } ` } className = "name" >
2023-03-01 17:55:35 +01:00
Anonymous </ span >}
& nbsp ;
2023-02-20 22:17:04 +01:00
& nbsp ;
< span className = "poster-address" >
2023-03-05 14:15:51 +01:00
( u /
2023-03-01 17:55:35 +01:00
{ comment . author . address . length > 20 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-am- ${ comment . cid } ` } id = "tt-address-mobile" className = "tooltip" />
< span key = { `pa- ${ comment . cid } ` } className = "poster-address"
2023-03-01 17:55:35 +01:00
data - tooltip - id = "tt-address-mobile"
data - tooltip - content = { comment . author . address }
data - tooltip - place = "top" >
{ comment . author . address . slice ( 0 , 20 ) + "..." }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `pa- ${ comment . cid } ` } className = "poster-address" >
2023-03-01 17:55:35 +01:00
{ comment . author . address }
</ span >})
2023-02-20 22:17:04 +01:00
</ span >
2023-02-22 11:22:36 +01:00
& nbsp ;
2023-03-05 14:15:51 +01:00
< span className = "date-time" data - utc = "data" >{ getDate ( comment . timestamp )}</ span >
2023-02-22 11:22:36 +01:00
& nbsp ;
< span className = "post-number" >
2023-03-07 13:54:14 +01:00
< Link to = "" onClick = { handleVoidClick } title = "Link to this post" > c / </ Link >
2023-03-17 14:35:03 +01:00
< button id = "reply-button" style = {{ all : 'unset' , cursor : 'pointer' }} onClick = { handleReplyOpen } title = "Reply to this post" >{ comment . cid . slice ( 0 , 8 )}</ button >
2023-03-16 13:55:39 +01:00
</ span > & nbsp ; & nbsp ;
< button key = { `pmb- ${ comment . cid } ` } className = "post-menu-button" onClick = { handleVoidClick } title = "Post menu" style = {{ all : 'unset' , cursor : 'pointer' }}> ▶ </ button >
2023-02-22 11:22:36 +01:00
< div id = "backlink-id" className = "backlink" >
2023-03-07 18:00:00 +01:00
{ comment . replies ? . pages . topAll . comments
. sort (( a , b ) => a . timestamp - b . timestamp )
. map (( reply ) => (
2023-03-11 12:32:42 +01:00
< div key = { `div- ${ reply . cid } ` } style = {{ display : 'inline-block' }}>
< Link to = { handleVoidClick } key = { `ql- ${ reply . cid } ` }
2023-03-08 09:49:42 +01:00
className = "quote-link"
onClick = {( event ) => handleQuoteClick ( reply , event )}>
2023-03-07 18:00:00 +01:00
c / { reply . cid . slice ( 0 , 8 )}</ Link >
& nbsp ;
</ div >
))
}
2023-02-22 11:22:36 +01:00
</ div >
</ span >
2023-02-20 22:17:04 +01:00
< blockquote >
2023-02-22 11:22:36 +01:00
{ comment . content }
2023-02-20 22:17:04 +01:00
</ blockquote >
</ div >
</ div >
</ div >
2023-02-21 22:12:12 +01:00
{ comment . replyCount > 0 &&
Object . keys ( comment . replies . pages . topAll . comments ). map (() => {
2023-03-08 09:49:42 +01:00
const renderedComments = renderThreadComments ( comment . replies . pages . topAll . comments );
2023-02-21 22:12:12 +01:00
return renderedComments . map ( reply => {
2023-02-20 22:17:04 +01:00
return (
2023-03-11 12:32:42 +01:00
< div key = { `pc- ${ reply . cid } ` } className = "reply-container" >
< div key = { `sa- ${ reply . cid } ` } className = "side-arrows" >{ '>>' }</ div >
< div key = { `pr- ${ reply . cid } ` } className = "post-reply" id = "post-reply" >
< div key = { `pi- ${ reply . cid } ` } className = "post-info" >
2023-02-21 22:12:12 +01:00
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `nb- ${ reply . cid } ` } className = "nameblock" >
2023-03-01 17:55:35 +01:00
{ reply . author . displayName
? reply . author . displayName . length > 20
? <>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-nm- ${ reply . cid } ` } id = "tt-name" className = "tooltip" />
< span key = { `mob-n- ${ reply . cid } ` } className = "name"
2023-03-01 17:55:35 +01:00
data - tooltip - id = "tt-name"
data - tooltip - content = { reply . author . displayName }
data - tooltip - place = "top" >
{ reply . author . displayName . slice ( 0 , 20 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ reply . cid } ` } className = "name" >
2023-03-01 17:55:35 +01:00
{ reply . author . displayName }</ span >
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ reply . cid } ` } className = "name" >
2023-03-01 17:55:35 +01:00
Anonymous </ span >}
2023-02-20 22:17:04 +01:00
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `pa- ${ reply . cid } ` } className = "poster-address" >
2023-03-05 14:15:51 +01:00
( u /
2023-03-01 17:55:35 +01:00
{ reply . author . address . length > 20 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-am- ${ reply . cid } ` } id = "tt-address" className = "tooltip" />
< span key = { `mob-ha- ${ reply . cid } ` }
2023-03-01 17:55:35 +01:00
data - tooltip - id = "tt-address"
data - tooltip - content = { reply . author . address }
data - tooltip - place = "top" >
{ reply . author . address . slice ( 0 , 20 ) + "..." }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-ha- ${ reply . cid } ` }>
2023-03-01 17:55:35 +01:00
{ reply . author . address }
</ span >})
2023-02-21 22:12:12 +01:00
</ span >
</ span >
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `dt- ${ reply . cid } ` } className = "date-time" data - utc = "data" >{ getDate ( reply . timestamp )}</ span >
2023-02-21 22:12:12 +01:00
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `pn- ${ reply . cid } ` } className = "post-number" >
< Link to = "" key = { `pl1- ${ reply . cid } ` } onClick = { handleVoidClick } title = "Link to this post" > c / </ Link >
2023-03-17 14:35:03 +01:00
< button id = "reply-button" style = {{ all : 'unset' , cursor : 'pointer' }} key = { `pl2- ${ reply . cid } ` } onClick = { handleReplyOpen } title = "Reply to this post" >{ reply . cid . slice ( 0 , 8 )}</ button >
2023-03-16 13:55:39 +01:00
</ span > & nbsp ;
< button key = { `pmb- ${ reply . cid } ` } className = "post-menu-button" onClick = { handleVoidClick } title = "Post menu" style = {{ all : 'unset' , cursor : 'pointer' }}> ▶ </ button >
2023-03-08 09:49:42 +01:00
< div id = "backlink-id" className = "backlink" >
{ reply . replies ? . pages . topAll . comments
. sort (( a , b ) => a . timestamp - b . timestamp )
. map (( reply ) => (
2023-03-11 12:32:42 +01:00
< div key = { `div- ${ reply . cid } ` } style = {{ display : 'inline-block' }}>
< Link to = { handleVoidClick } key = { `ql- ${ reply . cid } ` }
2023-03-08 09:49:42 +01:00
className = "quote-link"
onClick = {( event ) => handleQuoteClick ( reply , event )}>
c / { reply . cid . slice ( 0 , 8 )}</ Link >
& nbsp ;
</ div >
))
}
</ div >
2023-02-20 22:17:04 +01:00
</ div >
2023-03-11 12:32:42 +01:00
< blockquote key = { `pm- ${ reply . cid } ` } className = "post-message" >
2023-03-08 09:49:42 +01:00
< Link to = { handleVoidClick } className = "quote-link"
onClick = {( event ) => handleQuoteClick ( reply , event )}>
2023-03-06 14:49:59 +01:00
{ `c/ ${ reply . parentCid . slice ( 0 , 8 ) } ` }{< br />}
2023-03-07 13:54:14 +01:00
</ Link >
2023-02-21 22:12:12 +01:00
{ reply . content }
</ blockquote >
</ div >
</ div >
2023-02-20 22:17:04 +01:00
)
})
2023-02-21 22:12:12 +01:00
})}
2023-02-27 12:35:23 +01:00
</ div >
< div className = "thread-mobile" >
< hr />
< div className = "op-container" >
2023-03-11 12:32:42 +01:00
< div key = { `mob-po- ${ comment . cid } ` } className = "post op" >
< div key = { `mob-pi- ${ comment . cid } ` } className = "post-info-mobile" >
2023-03-16 13:55:39 +01:00
< button style = {{ all : 'unset' , cursor : 'pointer' }} key = { `mob-pb- ${ comment . cid } ` } className = "post-menu-button-mobile" onClick = { handleVoidClick }>...</ button >
2023-02-27 12:35:23 +01:00
< span className = "name-block-mobile" >
2023-02-28 16:34:33 +01:00
{ comment . author . displayName
? comment . author . displayName . length > 15
? <>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-nm- ${ comment . cid } ` } id = "tt-name-mobile" className = "tooltip" />
< span key = { `mob-n- ${ comment . cid } ` } className = "name-mobile"
2023-02-28 16:34:33 +01:00
data - tooltip - id = "tt-name-mobile"
data - tooltip - content = { comment . author . displayName }
data - tooltip - place = "top" >
{ comment . author . displayName . slice ( 0 , 15 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ comment . cid } ` } className = "name-mobile" >
2023-02-28 16:34:33 +01:00
{ comment . author . displayName }</ span >
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ comment . cid } ` } className = "name-mobile" >
2023-02-28 16:34:33 +01:00
Anonymous </ span >}
2023-02-27 12:35:23 +01:00
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `mob-pa- ${ comment . cid } ` } className = "poster-address-mobile" >
2023-03-05 14:15:51 +01:00
( u /
2023-02-28 16:34:33 +01:00
{ comment . author . address . length > 15 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-am- ${ comment . cid } ` } id = "tt-address-mobile" className = "tooltip" />
< span key = { `mob-ha- ${ comment . cid } ` } className = "highlight-address-mobile"
2023-02-28 16:34:33 +01:00
data - tooltip - id = "tt-address-mobile"
data - tooltip - content = { comment . author . address }
data - tooltip - place = "top" >
{ comment . author . address . slice ( 0 , 15 ) + "..." }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-ha- ${ comment . cid } ` } className = "highlight-address-mobile" >
2023-02-28 16:34:33 +01:00
{ comment . author . address }
</ span >}
) & nbsp ;
2023-02-27 12:35:23 +01:00
</ span >
2023-03-11 12:32:42 +01:00
< br key = { `mob-br1- ${ comment . cid } ` } />
2023-02-28 16:34:33 +01:00
{ comment . title ? (
comment . title . length > 30 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-tm- ${ comment . cid } ` } id = "tt-title-mobile" className = "tooltip" />
< span key = { `mob-t- ${ comment . cid } ` } className = "subject-mobile"
2023-02-28 16:34:33 +01:00
data - tooltip - id = "tt-title-mobile"
data - tooltip - content = { comment . title }
data - tooltip - place = "top" >
{ comment . title . slice ( 0 , 30 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-t- ${ comment . cid } ` } className = "subject-mobile" >
2023-02-28 16:34:33 +01:00
{ comment . title }
</ span >) : null }
2023-02-27 12:35:23 +01:00
</ span >
2023-03-11 12:32:42 +01:00
< span key = { `mob-dt- ${ comment . cid } ` } className = "date-time-mobile" >
2023-03-05 14:15:51 +01:00
{ getDate ( comment . timestamp )}
2023-02-27 12:35:23 +01:00
& nbsp ;
2023-03-17 14:35:03 +01:00
< button id = "reply-button" style = {{ all : 'unset' , cursor : 'pointer' }} key = { `mob-no- ${ comment . cid } ` } onClick = { handleReplyOpen } title = "Link to this post" > c / </ button >
2023-03-11 12:32:42 +01:00
< Link to = "" key = { `mob-no2- ${ comment . cid } ` } onClick = { handleVoidClick } title = "Reply to this post" >{ comment . cid . slice ( 0 , 8 )}</ Link >
2023-02-27 12:35:23 +01:00
</ span >
</ div >
2023-03-11 12:32:42 +01:00
< div key = { `mob-f- ${ comment . cid } ` } className = "file-mobile" >
2023-03-16 13:55:39 +01:00
< Link to = "" key = { `mob-ft ${ comment . cid } ` } className = "file-thumb-mobile" onClick = { handleVoidClick }>
2023-03-11 12:32:42 +01:00
< img key = { `mob-img- ${ comment . cid } ` } src = "/assets/plebchan-psycho.png" alt = "" />
< div key = { `mob-fi- ${ comment . cid } ` } className = "file-info-mobile" > 58 KB JPG </ div >
2023-03-07 13:54:14 +01:00
</ Link >
2023-02-27 12:35:23 +01:00
</ div >
2023-03-11 12:32:42 +01:00
< blockquote key = { `mob-bq- ${ comment . cid } ` } className = "post-message-mobile" >
2023-02-27 12:35:23 +01:00
{ comment . content ? (
<>
{ comment . content }
</>
) : null }
</ blockquote >
</ div >
</ div >
{ comment . replyCount > 0 &&
Object . keys ( comment . replies . pages . topAll . comments ). map (() => {
2023-03-08 09:49:42 +01:00
const renderedComments = renderThreadComments ( comment . replies . pages . topAll . comments );
2023-02-27 12:35:23 +01:00
return renderedComments . map ( reply => {
return (
2023-03-11 12:32:42 +01:00
< div key = { `mob-rc- ${ reply . cid } ` } className = "reply-container" >
< div key = { `mob-pr- ${ reply . cid } ` } className = "post-reply" >
< div key = { `mob-pi- ${ reply . cid } ` } className = "post-info-mobile" >
2023-03-16 13:55:39 +01:00
< button className = "post-menu-button-mobile" title = "Post menu" style = {{ all : 'unset' , cursor : 'pointer' }}>...</ button >
2023-03-11 12:32:42 +01:00
< span key = { `mob-nb- ${ reply . cid } ` } className = "name-block-mobile" >
2023-02-28 16:34:33 +01:00
{ reply . author . displayName
? reply . author . displayName . length > 12
? <>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-nm- ${ reply . cid } ` } id = "tt-name-mobile" className = "tooltip" />
< span key = { `mob-n- ${ reply . cid } ` } className = "name-mobile"
2023-02-28 16:34:33 +01:00
data - tooltip - id = "tt-name-mobile"
data - tooltip - content = { reply . author . displayName }
data - tooltip - place = "top" >
{ reply . author . displayName . slice ( 0 , 12 ) + " (...)" }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ reply . cid } ` } className = "name-mobile" >
2023-02-28 16:34:33 +01:00
{ reply . author . displayName }</ span >
2023-03-11 12:32:42 +01:00
: < span key = { `mob-n- ${ reply . cid } ` } className = "name-mobile" >
2023-02-28 16:34:33 +01:00
Anonymous </ span >}
2023-02-27 12:35:23 +01:00
& nbsp ;
2023-03-11 12:32:42 +01:00
< span key = { `mob-pa- ${ reply . cid } ` } className = "poster-address-mobile" >
2023-03-05 14:15:51 +01:00
( u /
2023-02-28 16:34:33 +01:00
{ reply . author . address . length > 12 ?
<>
2023-03-11 12:32:42 +01:00
< Tooltip key = { `mob-tt-am- ${ reply . cid } ` } id = "tt-address-mobile" className = "tooltip" />
< span key = { `mob-ha- ${ reply . cid } ` } className = "highlight-address-mobile"
2023-02-28 16:34:33 +01:00
data - tooltip - id = "tt-address-mobile"
data - tooltip - content = { reply . author . address }
data - tooltip - place = "top" >
{ reply . author . address . slice ( 0 , 12 ) + "..." }
</ span >
</>
2023-03-11 12:32:42 +01:00
: < span key = { `mob-ha- ${ reply . cid } ` } className = "highlight-address-mobile" >
2023-02-28 16:34:33 +01:00
{ reply . author . address }
</ span >}
2023-02-27 12:35:23 +01:00
)
</ span >
2023-03-11 12:32:42 +01:00
< br key = { `mob-br- ${ reply . cid } ` } />
2023-02-27 12:35:23 +01:00
</ span >
2023-03-11 12:32:42 +01:00
< span key = { `mob-dt- ${ reply . cid } ` } className = "date-time-mobile" >
2023-03-05 14:15:51 +01:00
{ getDate ( reply . timestamp )} & nbsp ;
2023-03-11 12:32:42 +01:00
< Link to = "" key = { `mob-pl1- ${ reply . cid } ` } onClick = { handleVoidClick } title = "Link to this post" > c / </ Link >
2023-03-17 14:35:03 +01:00
< button id = "reply-button" style = {{ all : 'unset' , cursor : 'pointer' }} key = { `mob-pl2- ${ reply . cid } ` } onClick = { handleReplyOpen } title = "Reply to this post" >{ reply . cid . slice ( 0 , 8 )}</ button >
2023-02-27 12:35:23 +01:00
</ span >
</ div >
2023-03-11 12:32:42 +01:00
< blockquote key = { `mob-pm- ${ reply . cid } ` } className = "post-message-mobile" >
< Link to = { handleVoidClick } key = { `mob-ql- ${ reply . cid } ` } className = "quotelink-mobile"
2023-03-08 09:49:42 +01:00
onClick = {( event ) => handleQuoteClick ( reply , event )}>
2023-03-06 14:49:59 +01:00
{ `c/ ${ reply . parentCid . slice ( 0 , 8 ) } ` }{< br />}
2023-03-07 13:54:14 +01:00
</ Link >
2023-02-27 12:35:23 +01:00
{ reply . content }
</ blockquote >
</ div >
</ div >
)
})
})}
</ div >
< BottomBar selectedStyle = { selectedStyle }>
2023-02-24 18:13:02 +01:00
< div id = "bottombar-desktop" >
< hr />
< span className = "bottom-bar-return" >
[
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } ` }> Return </ Link >
2023-02-24 18:13:02 +01:00
]
</ span >
< span className = "bottom-bar-catalog" >
[
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } /catalog` }> Catalog </ Link >
2023-02-24 18:13:02 +01:00
]
</ span >
< span className = "bottom-bar-top" >
[
2023-03-07 13:54:14 +01:00
< a onClick = { handleClickTop } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' } onTouchStart = { handleClickTop }> Top </ a >
2023-02-24 18:13:02 +01:00
]
</ span >
< span className = "quickreply-button" >
2023-02-21 22:12:12 +01:00
[
2023-03-07 13:54:14 +01:00
< Link to = "" onClick = { handleVoidClick } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' }> Post a Reply </ Link >
2023-02-21 22:12:12 +01:00
]
2023-02-24 18:13:02 +01:00
</ span >
{ comment . replyCount > 0 ? (
< span className = "reply-stat" >{ comment . replyCount } replies </ span >
) : (
< span className = "reply-stat" > No replies yet </ span >
)}
< hr />
</ div >
2023-02-21 22:12:12 +01:00
</ BottomBar >
2023-02-27 12:35:23 +01:00
< div id = "bottombar-mobile" >
< TopBar selectedStyle = { selectedStyle }>
< hr />
< span className = "style-changer" >
Style :
< select id = "style-selector" onChange = { handleStyleChange } value = { selectedStyle }>
< option value = "Yotsuba" > Yotsuba </ option >
2023-03-08 12:49:44 +01:00
< option value = "Yotsuba-B" > Yotsuba B </ option >
2023-02-27 12:35:23 +01:00
< option value = "Futaba" > Futaba </ option >
< option value = "Burichan" > Burichan </ option >
< option value = "Tomorrow" > Tomorrow </ option >
< option value = "Photon" > Photon </ option >
</ select >
</ span >
{ comment ? (
comment . replyCount > 0 ? (
< span className = "reply-stat" >{ comment . replyCount } replies </ span >
) : (
< span className = "reply-stat" > No replies yet </ span >
)) : (
null
)}
< hr />
</ TopBar >
2023-03-06 14:33:31 +01:00
< ReplyFormLink id = "post-form-link" selectedStyle = { selectedStyle } >
2023-02-27 12:35:23 +01:00
< div id = "post-form-link-mobile" className = "post-button-mobile" >
< span className = "btn-wrap" >
< a onClick = { handleClickForm } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' }> Post a Reply </ a >
2023-02-24 18:13:02 +01:00
</ span >
2023-02-27 12:35:23 +01:00
</ div >
< div id = "btns-container" >
< div id = "return-button-mobile" >
2023-02-24 18:13:02 +01:00
< span className = "btn-wrap" >
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } ` }> Return </ Link >
2023-02-24 18:13:02 +01:00
</ span >
</ div >
2023-02-27 12:35:23 +01:00
< div id = "catalog-button-mobile" >
< span className = "btn-wrap" >
2023-03-02 21:51:06 +01:00
< Link to = { `/ ${ selectedAddress } /catalog` }> Catalog </ Link >
2023-02-24 18:13:02 +01:00
</ span >
</ div >
2023-02-27 12:35:23 +01:00
< span className = "bottom-bar-top" >
< span className = "btn-wrap" >
2023-03-07 13:54:14 +01:00
< a onClick = { handleClickTop } onMouseOver = {( event ) => event . target . style . cursor = 'pointer' } onTouchStart = { handleClickTop }> Top </ a >
2023-02-27 12:35:23 +01:00
</ span >
</ span >
</ div >
</ ReplyFormLink >
2023-02-20 22:17:04 +01:00
</ div >
</>
) : (
< div > Loading ...</ div >
)}
</ BoardForm >
2023-02-12 21:20:08 +01:00
</ Container >
);
}
export default Thread ;