2017-06-06 23:19:12 +02:00
import React from "react" ;
2017-07-27 02:55:00 +02:00
import ReactDOM from "react-dom" ;
2017-06-06 23:19:12 +02:00
import lbryuri from "lbryuri" ;
import FileCard from "component/fileCard" ;
2017-07-27 02:55:00 +02:00
import { Icon , BusyMessage } from "component/common.js" ;
2017-06-06 23:19:12 +02:00
import ToolTip from "component/tooltip.js" ;
2016-04-10 02:00:56 +02:00
2017-07-27 02:55:00 +02:00
class FeaturedCategory extends React . PureComponent {
componentWillMount ( ) {
this . setState ( {
numItems : this . props . names . length ,
canScrollPrevious : false ,
canScrollNext : true ,
} ) ;
}
handleScrollPrevious ( ) {
const cardRow = ReactDOM . findDOMNode ( this . refs . rowitems ) ;
if ( cardRow . scrollLeft > 0 ) {
// check the visible cards
const cards = cardRow . getElementsByTagName ( "section" ) ;
let firstVisibleCard = null ;
let firstVisibleIdx = - 1 ;
for ( var i = 0 ; i < cards . length ; i ++ ) {
if ( this . isCardVisible ( cards [ i ] , cardRow , false ) ) {
firstVisibleCard = cards [ i ] ;
firstVisibleIdx = i ;
break ;
}
}
const numDisplayed = this . numDisplayedCards ( cardRow ) ;
const scrollToIdx = firstVisibleIdx - numDisplayed ;
const animationCallback = ( ) => {
this . setState ( {
canScrollPrevious : cardRow . scrollLeft !== 0 ,
canScrollNext : true ,
} ) ;
} ;
this . scrollCardItemsLeftAnimated (
cardRow ,
scrollToIdx < 0 ? 0 : cards [ scrollToIdx ] . offsetLeft ,
100 ,
animationCallback
) ;
}
}
handleScrollNext ( ) {
const cardRow = ReactDOM . findDOMNode ( this . refs . rowitems ) ;
// check the visible cards
const cards = cardRow . getElementsByTagName ( "section" ) ;
let lastVisibleCard = null ;
let lastVisibleIdx = - 1 ;
for ( var i = 0 ; i < cards . length ; i ++ ) {
if ( this . isCardVisible ( cards [ i ] , cardRow , true ) ) {
lastVisibleCard = cards [ i ] ;
lastVisibleIdx = i ;
}
}
if ( lastVisibleCard ) {
const numDisplayed = this . numDisplayedCards ( cardRow ) ;
const animationCallback = ( ) => {
// update last visible index after scroll
for ( var i = 0 ; i < cards . length ; i ++ ) {
if ( this . isCardVisible ( cards [ i ] , cardRow , true ) ) {
lastVisibleIdx = i ;
}
}
this . setState ( { canScrollPrevious : true } ) ;
if ( lastVisibleIdx === cards . length - 1 ) {
this . setState ( { canScrollNext : false } ) ;
}
} ;
this . scrollCardItemsLeftAnimated (
cardRow ,
Math . min (
lastVisibleCard . offsetLeft ,
cardRow . scrollWidth - cardRow . clientWidth
) ,
100 ,
animationCallback
) ;
}
}
scrollCardItemsLeftAnimated ( cardRow , target , duration , callback ) {
if ( ! duration || duration <= diff ) {
cardRow . scrollLeft = target ;
if ( callback ) {
callback ( ) ;
}
return ;
}
const component = this ;
const diff = target - cardRow . scrollLeft ;
const tick = diff / duration * 10 ;
setTimeout ( ( ) => {
cardRow . scrollLeft = cardRow . scrollLeft + tick ;
if ( cardRow . scrollLeft === target ) {
if ( callback ) {
callback ( ) ;
}
return ;
}
component . scrollCardItemsLeftAnimated (
cardRow ,
target ,
duration - 10 ,
callback
) ;
} , 10 ) ;
}
isCardVisible ( section , cardRow , partialVisibility ) {
// check if a card is fully or partialy visible in its parent
const cardRowWidth = cardRow . offsetWidth ;
const cardRowLeft = cardRow . scrollLeft ;
const cardRowEnd = cardRowLeft + cardRow . offsetWidth ;
const sectionLeft = section . offsetLeft - cardRowLeft ;
const sectionEnd = sectionLeft + section . offsetWidth ;
return (
( sectionLeft >= 0 && sectionEnd <= cardRowWidth ) ||
( ( ( sectionLeft < 0 && sectionEnd > 0 ) ||
( sectionLeft > 0 && sectionLeft <= cardRowWidth ) ) &&
partialVisibility )
) ;
}
numDisplayedCards ( cardRow ) {
const cards = cardRow . getElementsByTagName ( "section" ) ;
const cardRowWidth = cardRow . offsetWidth ;
// get the width of the first card and then calculate
const cardWidth = cards . length > 0 ? cards [ 0 ] . offsetWidth : 0 ;
if ( cardWidth > 0 ) {
return Math . ceil ( cardRowWidth / cardWidth ) ;
}
// return a default value of 1 card displayed if the card width couldn't be determined
return 1 ;
}
render ( ) {
const { category , names } = this . props ;
return (
< div className = "card-row card-row--small" >
< h3 className = "card-row__header" >
{ category }
{ category &&
category . match ( /^community/i ) &&
< ToolTip
label = { _ _ ( "What's this?" ) }
body = { _ _ (
'Community Content is a public space where anyone can share content with the rest of the LBRY community. Bid on the names "one," "two," "three," "four" and "five" to put your content here!'
) }
className = "tooltip--header"
/ > }
< / h3 >
2017-07-29 20:12:13 +02:00
< div className = "card-row__scrollhouse" >
{ this . state . canScrollPrevious &&
< div className = "card-row__nav card-row__nav--left" >
< a
className = "card-row__scroll-button"
onClick = { this . handleScrollPrevious . bind ( this ) }
>
< Icon icon = "icon-chevron-left" / >
< / a >
< / div > }
{ this . state . canScrollNext &&
< div className = "card-row__nav card-row__nav--right" >
< a
className = "card-row__scroll-button"
onClick = { this . handleScrollNext . bind ( this ) }
>
< Icon icon = "icon-chevron-right" / >
< / a >
< / div > }
< div ref = "rowitems" className = "card-row__items" >
{ names &&
names . map ( name =>
< FileCard
key = { name }
displayStyle = "card"
uri = { lbryuri . normalize ( name ) }
/ >
) }
< / div >
2017-07-27 02:55:00 +02:00
< / div >
< / div >
) ;
}
}
2016-05-16 15:20:32 +02:00
2017-06-08 06:42:19 +02:00
class DiscoverPage extends React . PureComponent {
2017-05-11 02:59:47 +02:00
componentWillMount ( ) {
2017-06-06 23:19:12 +02:00
this . props . fetchFeaturedUris ( ) ;
2017-05-07 09:39:13 +02:00
}
2017-06-29 09:58:15 +02:00
componentWillUnmount ( ) {
this . props . cancelResolvingUris ( ) ;
}
2017-05-11 02:59:47 +02:00
render ( ) {
2017-06-06 23:19:12 +02:00
const { featuredUris , fetchingFeaturedUris } = this . props ;
2017-07-15 21:24:57 +02:00
const hasContent =
typeof featuredUris === "object" && Object . keys ( featuredUris ) . length ,
failedToLoad = ! fetchingFeaturedUris && ! hasContent ;
2017-05-11 02:59:47 +02:00
return (
2017-09-18 02:52:57 +02:00
< main className = { hasContent && fetchingFeaturedUris ? "reloading" : null } >
2017-07-15 21:15:17 +02:00
{ ! hasContent &&
fetchingFeaturedUris &&
2017-07-15 21:24:57 +02:00
< BusyMessage message = { _ _ ( "Fetching content" ) } / > }
2017-07-15 21:15:17 +02:00
{ hasContent &&
2017-06-06 23:19:12 +02:00
Object . keys ( featuredUris ) . map (
category =>
featuredUris [ category ] . length
? < FeaturedCategory
key = { category }
category = { category }
names = { featuredUris [ category ] }
/ >
: ""
) }
{ failedToLoad &&
2017-06-29 09:58:15 +02:00
< div className = "empty" >
{ _ _ ( "Failed to load landing content." ) }
< / div > }
2017-05-22 17:22:24 +02:00
< / main >
2017-06-06 23:19:12 +02:00
) ;
2017-05-11 02:59:47 +02:00
}
2017-05-04 05:44:08 +02:00
}
2017-05-25 18:29:56 +02:00
export default DiscoverPage ;