// @flow import type { Node } from 'react'; import * as PAGES from 'constants/pages'; import * as ICONS from 'constants/icons'; import * as KEYCODES from 'constants/keycodes'; import React from 'react'; import Button from 'component/button'; import classnames from 'classnames'; import Icon from 'component/common/icon'; import NotificationBubble from 'component/notificationBubble'; import DebouncedInput from 'component/common/debounced-input'; import I18nMessage from 'component/i18nMessage'; import ChannelThumbnail from 'component/channelThumbnail'; import { useIsMobile, isTouch } from 'effects/use-screensize'; import { IS_MAC } from 'component/app/view'; import { useHistory } from 'react-router'; import { DOMAIN, ENABLE_UI_NOTIFICATIONS } from 'config'; const FOLLOWED_ITEM_INITIAL_LIMIT = 10; const touch = isTouch(); type SideNavLink = { title: string, link?: string, route?: string, onClick?: () => any, icon: string, extra?: Node, hideForUnauth?: boolean, }; // **************************************************************************** // **************************************************************************** type Props = { subscriptions: Array, followedTags: Array, email: ?string, uploadCount: number, doSignOut: () => void, sidebarOpen: boolean, setSidebarOpen: (boolean) => void, isMediumScreen: boolean, isOnFilePage: boolean, unseenCount: number, purchaseSuccess: boolean, doClearPurchasedUriSuccess: () => void, user: ?User, homepageData: any, activeChannelStakedLevel: number, }; function SideNavigation(props: Props) { const { subscriptions, doSignOut, email, purchaseSuccess, doClearPurchasedUriSuccess, sidebarOpen, setSidebarOpen, isMediumScreen, isOnFilePage, unseenCount, user, followedTags, } = props; const { location: { pathname }, } = useHistory(); const HOME = { title: 'Home', link: `/`, icon: ICONS.HOME, onClick: () => { if (pathname === '/') window.location.reload(); }, }; const RECENT_FROM_FOLLOWING = { title: 'Following --[sidebar button]--', link: `/$/${PAGES.CHANNELS_FOLLOWING}`, icon: ICONS.SUBSCRIBE, }; const DISCOVER = { title: 'Discover', link: `/$/${PAGES.DISCOVER}`, icon: ICONS.DISCOVER, }; const LIBRARY = { title: 'Library', link: `/$/${PAGES.LIBRARY}`, icon: ICONS.PURCHASED, }; const NOTIFICATIONS = { title: 'Notifications', link: `/$/${PAGES.NOTIFICATIONS}`, icon: ICONS.NOTIFICATION, extra: , }; const PLAYLISTS = { title: 'Lists', link: `/$/${PAGES.LISTS}`, icon: ICONS.STACK, }; const UNAUTH_LINKS: Array = [ { title: 'Log In', link: `/$/${PAGES.AUTH_SIGNIN}`, icon: ICONS.SIGN_IN, }, { title: 'Sign Up', link: `/$/${PAGES.AUTH}`, icon: ICONS.SIGN_UP, }, { title: 'Settings', link: `/$/${PAGES.SETTINGS}`, icon: ICONS.SETTINGS, }, { title: 'Help', link: `/$/${PAGES.HELP}`, icon: ICONS.HELP, }, ]; const MOBILE_LINKS: Array = [ { title: 'Upload', link: `/$/${PAGES.UPLOAD}`, icon: ICONS.PUBLISH, }, { title: 'New Channel', link: `/$/${PAGES.CHANNEL_NEW}`, icon: ICONS.CHANNEL, hideForUnauth: true, }, { title: 'Uploads', link: `/$/${PAGES.UPLOADS}`, icon: ICONS.PUBLISH, hideForUnauth: true, }, { title: 'Channels', link: `/$/${PAGES.CHANNELS}`, icon: ICONS.CHANNEL, hideForUnauth: true, }, { title: 'Creator Analytics', link: `/$/${PAGES.CREATOR_DASHBOARD}`, icon: ICONS.ANALYTICS, hideForUnauth: true, }, { title: 'Wallet', link: `/$/${PAGES.WALLET}`, icon: ICONS.WALLET, hideForUnauth: true, }, { title: 'Rewards', link: `/$/${PAGES.REWARDS}`, icon: ICONS.REWARDS, hideForUnauth: true, }, { title: 'Invites', link: `/$/${PAGES.INVITE}`, icon: ICONS.INVITE, hideForUnauth: true, }, { title: 'Settings', link: `/$/${PAGES.SETTINGS}`, icon: ICONS.SETTINGS, hideForUnauth: true, }, { title: 'Help', link: `/$/${PAGES.HELP}`, icon: ICONS.HELP, hideForUnauth: true, }, { title: 'Sign Out', onClick: doSignOut, icon: ICONS.SIGN_OUT, hideForUnauth: true, }, ]; const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui); const isAuthenticated = Boolean(email); const [pulseLibrary, setPulseLibrary] = React.useState(false); const [expandSubscriptions, setExpandSubscriptions] = React.useState(false); const [expandTags, setExpandTags] = React.useState(false); const isAbsolute = isOnFilePage || isMediumScreen; const isMobile = useIsMobile(); const [menuInitialized, setMenuInitialized] = React.useState(false); const menuCanCloseCompletely = (isOnFilePage && !isMobile) || (isMobile && menuInitialized); const hideMenuFromView = menuCanCloseCompletely && !sidebarOpen; const [canDisposeMenu, setCanDisposeMenu] = React.useState(false); React.useEffect(() => { if (hideMenuFromView || !menuInitialized) { const handler = setTimeout(() => { setMenuInitialized(true); setCanDisposeMenu(true); }, 250); return () => { clearTimeout(handler); }; } else { setCanDisposeMenu(false); } }, [hideMenuFromView, menuInitialized]); const shouldRenderLargeMenu = menuCanCloseCompletely || sidebarOpen; const showMicroMenu = !sidebarOpen && !menuCanCloseCompletely; const showPushMenu = sidebarOpen && !menuCanCloseCompletely; const showSubscriptionSection = shouldRenderLargeMenu && subscriptions && subscriptions.length > 0; const showTagSection = sidebarOpen && followedTags && followedTags.length; const [subscriptionFilter, setSubscriptionFilter] = React.useState(''); const filteredSubscriptions = subscriptions.filter( (sub) => !subscriptionFilter || sub.channelName.toLowerCase().includes(subscriptionFilter.toLowerCase()) ); let displayedSubscriptions = filteredSubscriptions; if ( showSubscriptionSection && !subscriptionFilter && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && !expandSubscriptions ) { displayedSubscriptions = subscriptions.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT); } let displayedFollowedTags = followedTags; if (showTagSection && followedTags.length > FOLLOWED_ITEM_INITIAL_LIMIT && !expandTags) { displayedFollowedTags = followedTags.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT); } function getLink(props: SideNavLink) { const { hideForUnauth, route, link, ...passedProps } = props; const { title, icon, extra } = passedProps; if (hideForUnauth && !email) { return null; } return (
  • ); } function getSubscriptionSection() { if (showSubscriptionSection) { return ( <>
      {subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
    • )} {displayedSubscriptions.map((subscription) => ( ))} {!!subscriptionFilter && !displayedSubscriptions.length && (
    • {__('No results')}
    • )} {!subscriptionFilter && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
    ); } return null; } function getFollowedTagsSection() { if (showTagSection) { return ( <>
      {displayedFollowedTags.map(({ name }, key) => (
    • ))} {followedTags.length > FOLLOWED_ITEM_INITIAL_LIMIT && (
    ); } return null; } React.useEffect(() => { if (purchaseSuccess) { setPulseLibrary(true); let timeout = setTimeout(() => { setPulseLibrary(false); doClearPurchasedUriSuccess(); }, 2500); return () => clearTimeout(timeout); } }, [setPulseLibrary, purchaseSuccess, doClearPurchasedUriSuccess]); React.useEffect(() => { function handleKeydown(e: SyntheticKeyboardEvent<*>) { if (e.keyCode === KEYCODES.ESCAPE && isAbsolute) { setSidebarOpen(false); } else if (e.keyCode === KEYCODES.BACKSLASH) { const hasActiveInput = document.querySelector('input:focus, textarea:focus'); if (!hasActiveInput) { setSidebarOpen(!sidebarOpen); } } } window.addEventListener('keydown', handleKeydown); return () => window.removeEventListener('keydown', handleKeydown); }, [sidebarOpen, setSidebarOpen, isAbsolute]); const unAuthNudge = DOMAIN === 'lbry.tv' ? null : (
    }}> Sign up to earn %lbc% for you and your favorite creators.
    ); const helpLinks = (
    ); return (
    setSidebarOpen(false)} />
    ); } function SubscriptionListItem({ subscription }: { subscription: Subscription }) { const { uri, channelName } = subscription; return (
  • ); } export default SideNavigation;