[Header] Changes, fixes and improvements (#493)
This commit is contained in:
commit
ebcbc8cdb8
39 changed files with 863 additions and 848 deletions
|
@ -52,8 +52,8 @@ YRBL_HAPPY_IMG_URL=https://spee.ch/spaceman-happy:a.png?quality=85&height=457&wi
|
||||||
YRBL_SAD_IMG_URL=https://spee.ch/spaceman-sad:d.png?quality=85&height=457&width=457
|
YRBL_SAD_IMG_URL=https://spee.ch/spaceman-sad:d.png?quality=85&height=457&width=457
|
||||||
LOGIN_IMG_URL=https://cdn.lbryplayer.xyz/speech/odysee-sign-up:d.png
|
LOGIN_IMG_URL=https://cdn.lbryplayer.xyz/speech/odysee-sign-up:d.png
|
||||||
LOGO=https://spee.ch/odysee-logo-png:3.png?quality=85&height=200&width=200
|
LOGO=https://spee.ch/odysee-logo-png:3.png?quality=85&height=200&width=200
|
||||||
LOGO_TEXT_LIGHT=https://spee.ch/odysee-white-png:f.png?quality=85&height=300&width=1000
|
LOGO_WHITE_TEXT=https://spee.ch/odysee-white-png:f.png?quality=85&height=300&width=1000
|
||||||
LOGO_TEXT_DARK=https://spee.ch/odysee-png:2.png?quality=85&height=300&width=1000
|
LOGO_DARK_TEXT=https://spee.ch/odysee-png:2.png?quality=85&height=300&width=1000
|
||||||
AVATAR_DEFAULT=https://spee.ch/spaceman-png:2.png?quality=85&height=180&width=180
|
AVATAR_DEFAULT=https://spee.ch/spaceman-png:2.png?quality=85&height=180&width=180
|
||||||
MISSING_THUMB_DEFAULT=https://spee.ch/missing-thumb-png?quality=85&height=390&width=220
|
MISSING_THUMB_DEFAULT=https://spee.ch/missing-thumb-png?quality=85&height=390&width=220
|
||||||
FAVICON=https://spee.ch/favicon-png:c.png
|
FAVICON=https://spee.ch/favicon-png:c.png
|
||||||
|
|
|
@ -35,8 +35,8 @@ const config = {
|
||||||
// LOGO
|
// LOGO
|
||||||
LOGO_TITLE: process.env.LOGO_TITLE,
|
LOGO_TITLE: process.env.LOGO_TITLE,
|
||||||
LOGO: process.env.LOGO,
|
LOGO: process.env.LOGO,
|
||||||
LOGO_TEXT_LIGHT: process.env.LOGO_TEXT_LIGHT,
|
LOGO_WHITE_TEXT: process.env.LOGO_WHITE_TEXT,
|
||||||
LOGO_TEXT_DARK: process.env.LOGO_TEXT_DARK,
|
LOGO_DARK_TEXT: process.env.LOGO_DARK_TEXT,
|
||||||
AVATAR_DEFAULT: process.env.AVATAR_DEFAULT,
|
AVATAR_DEFAULT: process.env.AVATAR_DEFAULT,
|
||||||
MISSING_THUMB_DEFAULT: process.env.MISSING_THUMB_DEFAULT,
|
MISSING_THUMB_DEFAULT: process.env.MISSING_THUMB_DEFAULT,
|
||||||
// OG
|
// OG
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
STATUS_DOWN,
|
STATUS_DOWN,
|
||||||
} from 'web/effects/use-degraded-performance';
|
} from 'web/effects/use-degraded-performance';
|
||||||
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
||||||
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
|
|
||||||
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "fileDrop" */));
|
const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "fileDrop" */));
|
||||||
const NagContinueFirstRun = lazyImport(() => import('component/nagContinueFirstRun' /* webpackChunkName: "nagCFR" */));
|
const NagContinueFirstRun = lazyImport(() => import('component/nagContinueFirstRun' /* webpackChunkName: "nagCFR" */));
|
||||||
|
@ -122,6 +123,7 @@ function App(props: Props) {
|
||||||
fetchModAmIList,
|
fetchModAmIList,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const isMobile = useIsMobile();
|
||||||
const appRef = useRef();
|
const appRef = useRef();
|
||||||
const isEnhancedLayout = useKonamiListener();
|
const isEnhancedLayout = useKonamiListener();
|
||||||
const [hasSignedIn, setHasSignedIn] = useState(false);
|
const [hasSignedIn, setHasSignedIn] = useState(false);
|
||||||
|
@ -154,7 +156,7 @@ function App(props: Props) {
|
||||||
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
const shouldMigrateLanguage = LANGUAGE_MIGRATIONS[language];
|
||||||
const hasActiveChannelClaim = activeChannelId !== undefined;
|
const hasActiveChannelClaim = activeChannelId !== undefined;
|
||||||
const isPersonalized = !IS_WEB || hasVerifiedEmail;
|
const isPersonalized = !IS_WEB || hasVerifiedEmail;
|
||||||
const renderFiledrop = !IS_WEB || isAuthenticated;
|
const renderFiledrop = !isMobile && isAuthenticated;
|
||||||
const isOnline = navigator.onLine;
|
const isOnline = navigator.onLine;
|
||||||
|
|
||||||
let uri;
|
let uri;
|
||||||
|
|
|
@ -41,7 +41,7 @@ function ChannelStakedIndicator(props: Props) {
|
||||||
return (
|
return (
|
||||||
SIMPLE_SITE && (
|
SIMPLE_SITE && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
label={
|
title={
|
||||||
<div className="channel-staked__tooltip">
|
<div className="channel-staked__tooltip">
|
||||||
<div className="channel-staked__tooltip-icons">
|
<div className="channel-staked__tooltip-icons">
|
||||||
<LevelIcon icon={icon} isControlling={isControlling} size={isControlling ? 14 : 10} />
|
<LevelIcon icon={icon} isControlling={isControlling} size={isControlling ? 14 : 10} />
|
||||||
|
|
|
@ -250,7 +250,7 @@ function Comment(props: Props) {
|
||||||
<div className="comment__meta">
|
<div className="comment__meta">
|
||||||
<div className="comment__meta-information">
|
<div className="comment__meta-information">
|
||||||
{isGlobalMod && (
|
{isGlobalMod && (
|
||||||
<Tooltip label={__('Admin')}>
|
<Tooltip title={__('Admin')}>
|
||||||
<span className="comment__badge comment__badge--global-mod">
|
<span className="comment__badge comment__badge--global-mod">
|
||||||
<Icon icon={ICONS.BADGE_MOD} size={20} />
|
<Icon icon={ICONS.BADGE_MOD} size={20} />
|
||||||
</span>
|
</span>
|
||||||
|
@ -258,7 +258,7 @@ function Comment(props: Props) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isModerator && (
|
{isModerator && (
|
||||||
<Tooltip label={__('Moderator')}>
|
<Tooltip title={__('Moderator')}>
|
||||||
<span className="comment__badge comment__badge--mod">
|
<span className="comment__badge comment__badge--mod">
|
||||||
<Icon icon={ICONS.BADGE_MOD} size={20} />
|
<Icon icon={ICONS.BADGE_MOD} size={20} />
|
||||||
</span>
|
</span>
|
||||||
|
|
22
ui/component/common/header-menu-link.jsx
Normal file
22
ui/component/common/header-menu-link.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// @flow
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { MenuLink } from '@reach/menu-button';
|
||||||
|
import Icon from 'component/common/icon';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
icon: string,
|
||||||
|
name: string,
|
||||||
|
page: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function HeaderMenuLink(props: Props) {
|
||||||
|
const { icon, name, page } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuLink className="menu__link" as={Link} to={`/$/${page}`}>
|
||||||
|
<Icon aria-hidden icon={icon} />
|
||||||
|
{name}
|
||||||
|
</MenuLink>
|
||||||
|
);
|
||||||
|
}
|
|
@ -42,19 +42,170 @@ const buildIcon = (iconStrokes: React$Node, customSvgValues = {}) =>
|
||||||
});
|
});
|
||||||
|
|
||||||
export const icons = {
|
export const icons = {
|
||||||
// The LBRY icon is different from the base icon set so don't use buildIcon()
|
[ICONS.ODYSEE_LOGO]: (props: IconProps) => (
|
||||||
[ICONS.LBRY]: (props: IconProps) => (
|
|
||||||
<svg
|
<svg
|
||||||
{...props}
|
{...props}
|
||||||
stroke="currentColor"
|
id="Layer_1"
|
||||||
fill="currentColor"
|
strokeWidth="0"
|
||||||
|
style={{ enableBackground: 'new 0 0 103.1 103.1' }}
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 103.1 103.1"
|
||||||
x="0px"
|
x="0px"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlSpace="preserve"
|
||||||
y="0px"
|
y="0px"
|
||||||
viewBox="0 0 322 254"
|
|
||||||
className="icon lbry-icon"
|
|
||||||
>
|
>
|
||||||
<path d="M296,85.9V100l-138.8,85.3L52.6,134l0.2-7.9l104,51.2L289,96.1v-5.8L164.2,30.1L25,116.2v38.5l131.8,65.2 l137.6-84.4l3.9,6l-141.1,86.4L18.1,159.1v-46.8l145.8-90.2C163.9,22.1,296,85.9,296,85.9z" />
|
<style type="text/css">
|
||||||
<path d="M294.3,150.9l2-12.6l-12.2-2.1l0.8-4.9l17.1,2.9l-2.8,17.5L294.3,150.9L294.3,150.9z" />
|
{
|
||||||
|
'.st0{fill:url(#SVGID_1_);}.st1{clip-path:url(#SVGID_00000146468834146730603410000007600185482987846543_);}.st2{fill:#FFFFFF;}'
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<linearGradient
|
||||||
|
id="SVGID_1_"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="37.1511"
|
||||||
|
y1="1.7925"
|
||||||
|
x2="79.9092"
|
||||||
|
y2="149.7319"
|
||||||
|
>
|
||||||
|
<stop offset="0" style={{ stopColor: '#EF1970' }} />
|
||||||
|
<stop offset="0.1438" style={{ stopColor: '#F23B5C' }} />
|
||||||
|
<stop offset="0.445" style={{ stopColor: '#F77D35' }} />
|
||||||
|
<stop offset="0.6983" style={{ stopColor: '#FCAD18' }} />
|
||||||
|
<stop offset="0.8909" style={{ stopColor: '#FECB07' }} />
|
||||||
|
<stop offset="1" style={{ stopColor: '#FFD600' }} />
|
||||||
|
</linearGradient>
|
||||||
|
<path
|
||||||
|
className="st0"
|
||||||
|
d="M51.5,103.1L51.5,103.1C23.1,103.1,0,80,0,51.5v0C0,23.1,23.1,0,51.5,0h0c28.5,0,51.5,23.1,51.5,51.5v0C103.1,80,80,103.1,51.5,103.1z"
|
||||||
|
/>
|
||||||
|
<g>
|
||||||
|
<defs>
|
||||||
|
<path
|
||||||
|
id="SVGID_00000170984886341847456420000000262070696033326467_"
|
||||||
|
d="M51.5,103.1L51.5,103.1C23.1,103.1,0,80,0,51.5v0C0,23.1,23.1,0,51.5,0h0c28.5,0,51.5,23.1,51.5,51.5v0C103.1,80,80,103.1,51.5,103.1z"
|
||||||
|
/>
|
||||||
|
</defs>
|
||||||
|
<clipPath id="SVGID_00000173159025839821803030000017583277320152650913_">
|
||||||
|
<use
|
||||||
|
xlinkHref="#SVGID_00000170984886341847456420000000262070696033326467_"
|
||||||
|
style={{ overflow: 'visible' }}
|
||||||
|
/>
|
||||||
|
</clipPath>
|
||||||
|
<g style={{ clipPath: 'url(#SVGID_00000173159025839821803030000017583277320152650913_)' }}>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
className="st2"
|
||||||
|
d="M8.7,40.1c0.5-0.3,0.6-0.9,0.3-1.3c-0.3-0.4-0.9-0.6-1.3-0.3c-0.4,0.3-0.6,0.9-0.3,1.3C7.7,40.3,8.3,40.5,8.7,40.1z M64.8,15c0.5-0.3,0.6-0.8,0.3-1.3c-0.3-0.4-0.9-0.6-1.3-0.3c-0.4,0.3-0.6,0.9-0.3,1.3C63.8,15.1,64.4,15.3,64.8,15z M76.7,51.4c-0.1,0.6,0.2,1.2,0.8,1.3c0.6,0.1,1.2-0.2,1.3-0.8c0.1-0.6-0.2-1.2-0.8-1.3C77.4,50.5,76.9,50.8,76.7,51.4z M60.9,88.2c-0.4-0.2-0.8,0.1-1,0.6c-0.1,0.5,0.2,0.9,0.6,1c0.5,0.1,0.9-0.2,1-0.6C61.7,88.7,61.4,88.3,60.9,88.2z M15.1,20.2c0.3,0.1,0.6-0.1,0.6-0.4c0.1-0.3-0.1-0.6-0.4-0.6c-0.3,0-0.6,0.1-0.6,0.4C14.6,19.9,14.8,20.2,15.1,20.2z M18.3,70.3c-0.4,0.1-0.7,0.4-0.6,0.8c0.1,0.4,0.4,0.7,0.8,0.6c0.4,0,0.6-0.4,0.6-0.8C19,70.5,18.7,70.2,18.3,70.3z M85.5,36l-0.6,2.6l-2.3,1.1l2.6,0.6l1.1,2.3l0.6-2.6l2.3-1.1l-2.6-0.6L85.5,36z M51.3,18.7c-0.6,0.2-0.8,0.8-0.6,1.4c0.5,1.2,0.5,1.8,0.3,3c-0.1,0.6,0.3,1.2,0.9,1.3c0.1,0,0.1,0,0.2,0c0.5,0,1-0.4,1-0.9c0.4-1.6,0.2-2.7-0.4-4.2C52.6,18.7,51.9,18.5,51.3,18.7z M50.8,14.4c-0.5-1-0.9-1.4-1-1.5c-0.4-0.4-1.1-0.4-1.5,0c-0.4,0.4-0.4,1.1,0,1.5c0,0,0.2,0.2,0.6,1c0.2,0.4,0.6,0.6,1,0.6c0.1,0,0.3,0,0.5-0.1C50.9,15.6,51.1,14.9,50.8,14.4zM89.2,85.1c-1.3-5.8-3.1-10.9-6.1-18.5c-2-5.2-8.8-11.6-13.1-14.8c-1.6-1.2-1.7-3.4-0.3-4.9C74,42.9,81.6,35,84,30.8c1.6-2.9,4.7-8.5,4.9-13.3C89.2,14,88.7,9.9,84,8c-4.3-1.7-7.1,0.9-7.1,0.9c-3,2.1-3.9,7.7-6.1,13.3c-2.4,6.5-6.3,7.3-8.3,7.3c-1.9,0-0.7-2.1-5.4-15.6c-4.7-13.4-17-11-26.3-5.4c-11.8,7.1-6.6,22.1-3.6,31.9c-1.6,1.6-7.9,2.8-13.5,5.9c-3.5,1.9-6.5,3.1-9.5,5.5c-4.1,3.3-5.9,7-4.4,12.1c0.3,1.1,1.4,2.9,3.6,4.1c3.3,1.5,8.3-0.7,15.8-6.3c5.5-3.7,11.9-5.6,11.9-5.6s4.6,7,8.8,15.3c4.2,8.3-4.6,11-5.5,11c-1,0-14.8-1.3-11.6,10.4c3,11.6,19.9,7.5,28.5,1.8s6.5-24.2,6.5-24.2c8.4-1.3,11,7.6,11.8,12.1c0.8,4.5-1,12.4,7.5,12.6c1.2,0,2.4-0.2,3.5-0.5c4.6-1.1,7.2-3.4,8.3-5.8C89.4,87.6,89.5,86.3,89.2,85.1z M46.9,30.1c-8.6,3.2-12.7-1-13.2-8.8c-0.6-8.8,7.6-11,7.6-11c9.1-3,11.5,1.3,13.7,7.8C57,24.6,55.4,26.9,46.9,30.1z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
[ICONS.ODYSEE_WHITE_TEXT]: (props: IconProps) => (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
data-name="Layer 1"
|
||||||
|
id="Layer_1"
|
||||||
|
strokeWidth="0"
|
||||||
|
viewBox="0 0 397 119.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
{'.cls-1{fill:none;}.cls-2{fill:#fff;}.cls-3{fill:url(#linear-gradient);}.cls-4{clip-path:url(#clip-path);}'}
|
||||||
|
</style>
|
||||||
|
<linearGradient id="linear-gradient" x1="45.6" y1="9.82" x2="88.36" y2="157.76" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0" stopColor="#ef1970" />
|
||||||
|
<stop offset="0.14" stopColor="#f23b5c" />
|
||||||
|
<stop offset="0.45" stopColor="#f77d35" />
|
||||||
|
<stop offset="0.7" stopColor="#fcad18" />
|
||||||
|
<stop offset="0.89" stopColor="#fecb07" />
|
||||||
|
<stop offset="1" stopColor="#ffd600" />
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath id="clip-path">
|
||||||
|
<rect x="8.45" y="8.03" width="103.05" height="103.05" rx="51.52" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M216,36.55A105.13,105.13,0,0,0,214.51,25c-.21-1.11-.45-2.47-.78-4.44s-.61-3.46-.83-4.51-.45-2-.68-2.85A5,5,0,0,0,211,10.74a4.62,4.62,0,0,0-1.61-1,6.27,6.27,0,0,0-2-.28c-.78,0-3.16,0-4.16,1.74-.39.67-.74,1.81-.74,5.57a14.41,14.41,0,0,0,.14,2.48l.14,1.12a40.39,40.39,0,0,0,.89,5.22,2.86,2.86,0,0,0,.12.35,11.3,11.3,0,0,0,.15,1.36,12.27,12.27,0,0,0,.56,2.47,6.14,6.14,0,0,1,.3,1.78c.48,5.45.35,6.88.3,7.28a1.07,1.07,0,0,1-.48.07c-1.4,0-15.06,4-18.61,6.36a22.12,22.12,0,0,0-7.78,8C176.52,56.48,176,74.82,176,75c-.09,4.22.64,6.82,2.27,8.14l.32.35a18.94,18.94,0,0,0,11.85,6.2,88.44,88.44,0,0,0,14.48.73c1.79,0,3.48,0,5.06,0h.3l7.36-2.4-.24-14C217.36,67.55,216.89,46.57,216,36.55ZM207.2,74.16c-.11.88-.2,1.55-.27,2a4.85,4.85,0,0,1-.28,1c-.07.17-.13.29-.14.33l-.24.1a2.82,2.82,0,0,1-.8.15c-.42,0-1,0-1.84,0a45.33,45.33,0,0,1-9.91-1.43,30.77,30.77,0,0,1-5.88-1.77h0c-.8-1.88,1.22-16,6.72-20.09s8.27-4.54,9.65-4.11c.38.12,1.54.48,2.33,3,.2,1,.41,7.6.52,11.15.08,2.47.14,4.51.19,5.14A22.23,22.23,0,0,1,207.2,74.16Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M251.17,34.44A8.26,8.26,0,0,0,248.7,38l0,.06a41,41,0,0,1-2.6,5.89,10.94,10.94,0,0,0-1.38,4.79A4.41,4.41,0,0,1,244.4,50a5.3,5.3,0,0,1-.55,1.17l-.44-.28a26.83,26.83,0,0,1-2.5-2.09c-1-1-2.35-2.29-4-4-7.07-7.19-11.28-9.75-14.07-8.62-1.59.65-2.4,2.31-2.4,4.94,0,1.63.85,3.69,2.61,6.27a96.53,96.53,0,0,0,7.64,9.36c5.21,5.9,8.73,7.54,10.36,8.23a21.38,21.38,0,0,1-.37,4.4,45.35,45.35,0,0,1-1.89,5.06,42,42,0,0,0-2.5,6.39,20.24,20.24,0,0,0-1.06,5.49c0,2.11.3,3.41,1,4.22a3.19,3.19,0,0,0,2.57,1.06,5.87,5.87,0,0,0,1.21-.13,7.75,7.75,0,0,0,3-1.1,5.46,5.46,0,0,0,2.12-2.15c.18-.34.58-1.13,1.19-2.37s1-2.08,1.24-2.56a25,25,0,0,0,1.92-5.43c.7-2.58,1.34-5.32,1.88-8.11s1.44-6,2.48-9.67,2-6.73,2.85-9.09c1.16-3.07,2-5.52,2.56-7.5a19.84,19.84,0,0,0,.88-5.21,5.07,5.07,0,0,0-1.35-3.85C257,32.86,253.27,32.86,251.17,34.44Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M296.7,35.06a3.39,3.39,0,0,0-1.31-.87A5.37,5.37,0,0,0,294,33.8c-.33,0-.87-.08-1.61-.12s-1.39-.06-2-.08-1.56,0-2.75,0c-6,0-10.18.83-12.84,2.55a17.31,17.31,0,0,0-7.18,8.16c-1.41,3.3-2.13,7.74-2.13,13.17l-.12,10.68,11,3.6c3.51,1.15,5.37,1.87,6.35,2.3a15.28,15.28,0,0,1-2.6.73,24.58,24.58,0,0,1-5.24.57,38,38,0,0,0-4.87.21A4.88,4.88,0,0,0,267,76.75a4,4,0,0,0-1,2.93A5.37,5.37,0,0,0,268.22,84a11.22,11.22,0,0,0,4.94,2,26.55,26.55,0,0,0,4.73.4l1.2,0a25.46,25.46,0,0,0,6.49-1.14,20.68,20.68,0,0,0,5.84-2.8,13.33,13.33,0,0,0,3.76-3.92,10.08,10.08,0,0,0,1.06-5,9,9,0,0,0-3.14-7.37c-1.87-1.5-5.33-3-10.56-4.44-5.54-1.67-6.51-2.49-6.7-2.71s-.7-1.29.68-4.65a23.14,23.14,0,0,1,5.14-7.64c2.55-2.54,3.78-3.27,4.28-3.48s1.66-.46,4.33-.08c1,.15,1.77.25,2.27.3a9.47,9.47,0,0,0,1.76,0,4.44,4.44,0,0,0,1.61-.37,2.83,2.83,0,0,0,1.24-1.33,4,4,0,0,0,.42-1.58c0-.35,0-.87,0-1.57V37.65a4,4,0,0,0-.26-1.4A3.59,3.59,0,0,0,296.7,35.06Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M341.77,41.73a8.9,8.9,0,0,0-1-1.91,13,13,0,0,0-1.64-2l-1.61-1.68a19.65,19.65,0,0,0-5.45-4.2,16.56,16.56,0,0,0-6.49-1,19.81,19.81,0,0,0-11.31,3.24h0a30.8,30.8,0,0,0-6.52,5.73,17.93,17.93,0,0,0-3.4,6.7,45.67,45.67,0,0,0-1.29,9.6c-.57,10.37,1.22,18.06,5.31,22.88,3.78,4.44,9.71,6.69,17.69,6.69.81,0,1.64,0,2.49-.07l3.38-.25a21.33,21.33,0,0,0,2.43-.32,7.45,7.45,0,0,0,2-.56,3.81,3.81,0,0,0,1.33-1.14,3.5,3.5,0,0,0,.74-1.75,14.71,14.71,0,0,0,.07-1.59c0-1.39-.17-3.34-1.63-4.21-.67-.39-1.77-.68-5.28-.24a16.13,16.13,0,0,1-9-1.7,13.27,13.27,0,0,1-6.38-5.67l-.84-1.58,5.84-.64a34.24,34.24,0,0,0,8-1.56,27.41,27.41,0,0,0,6.56-3.33c1.4-1,2.42-1.75,3.07-2.31a8.54,8.54,0,0,0,2-2.56,9.49,9.49,0,0,0,1.05-3.07c.13-.87.26-2.23.37-4.08q.12-1.87.12-3a18.62,18.62,0,0,0-.15-2.37A11.51,11.51,0,0,0,341.77,41.73ZM316.33,53.11l-1.68-1.74,4.24-4.11A32,32,0,0,1,323,43.63a20.31,20.31,0,0,1,2-1.27,5,5,0,0,1,1.52.92,18.22,18.22,0,0,1,2.93,2.8l2.54,3-2.26,2a14.46,14.46,0,0,1-3.48,2.14,17.43,17.43,0,0,1-4,1.4,9.45,9.45,0,0,1-3.66.14A5.19,5.19,0,0,1,316.33,53.11Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M387.35,46.9a10.38,10.38,0,0,0-.43-2,7.76,7.76,0,0,0-1-1.92,12.53,12.53,0,0,0-1.42-1.8l-1.82-1.91a19.86,19.86,0,0,0-5.46-4.2,16.66,16.66,0,0,0-6.48-1,19.84,19.84,0,0,0-11.32,3.24h0A31.34,31.34,0,0,0,352.91,43a18.23,18.23,0,0,0-3.4,6.7,45.1,45.1,0,0,0-1.28,9.6c-.57,10.37,1.21,18.07,5.31,22.88,3.77,4.44,9.71,6.69,17.68,6.69.81,0,1.64,0,2.49-.07l3.39-.25a19.3,19.3,0,0,0,2.43-.32,7.71,7.71,0,0,0,2-.55,3.82,3.82,0,0,0,1.34-1.14,3.54,3.54,0,0,0,.74-1.76,14.71,14.71,0,0,0,.07-1.59c0-1.39-.17-3.34-1.64-4.21-.67-.39-1.77-.68-5.27-.24a16.09,16.09,0,0,1-9-1.7,13.29,13.29,0,0,1-6.37-5.67l-.85-1.57,5.85-.65a34.15,34.15,0,0,0,8-1.56,27.23,27.23,0,0,0,6.56-3.33c1.4-1,2.43-1.75,3.07-2.3a8.82,8.82,0,0,0,2-2.56,9.87,9.87,0,0,0,1-3.08c.13-.87.26-2.23.37-4.08.08-1.25.11-2.24.11-3A18.62,18.62,0,0,0,387.35,46.9Zm-25.86,9.34-1.68-1.74L364,50.39a33.45,33.45,0,0,1,4.15-3.63,18.65,18.65,0,0,1,2-1.26,5,5,0,0,1,1.52.91,18.17,18.17,0,0,1,2.92,2.8l2.55,3-2.27,2a15.16,15.16,0,0,1-3.47,2.14,17.83,17.83,0,0,1-4,1.39,9.23,9.23,0,0,1-3.66.14A5.08,5.08,0,0,1,361.49,56.24Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M135.65,41.29a21.51,21.51,0,0,1,5.44-1,82,82,0,0,1,8.25-.4c4.56,0,7.65.16,9.28.62A14.23,14.23,0,0,1,164.13,44a16.32,16.32,0,0,1,3.68,5.32,31.66,31.66,0,0,1,1.73,8.12,48.43,48.43,0,0,1-.46,15.29q-1.43,7.38-4.3,9a60,60,0,0,0-7.43,5.2,13.3,13.3,0,0,1-5,2.69,22.19,22.19,0,0,1-6.71-.09,23.84,23.84,0,0,1-7.13-2.26A28.75,28.75,0,0,1,132,82.05q-1.89-1.86-2.7-2.7a14.72,14.72,0,0,1-1.73-2.23A11.59,11.59,0,0,1,126.4,75a15.75,15.75,0,0,1-.56-2.61,22.94,22.94,0,0,1-.29-3.4V64.15Q125.55,45.13,135.65,41.29Zm20,8.79q-4.53-4.3-5.66-4.3c-1.62,0-3.68,1-6.19,2.83a25.06,25.06,0,0,0-6.07,6.2q-3.8,5.53-3.42,10t5.1,9.61l5.23,5.67,6.41-2.93A17.64,17.64,0,0,0,159.5,70a14.09,14.09,0,0,0,1.71-10A18.78,18.78,0,0,0,155.67,50.08Z"
|
||||||
|
/>
|
||||||
|
<rect className="cls-3" x="8.45" y="8.03" width="103.05" height="103.05" rx="51.52" />
|
||||||
|
<g className="cls-4">
|
||||||
|
<path
|
||||||
|
className="cls-2"
|
||||||
|
d="M17.12,48.17a.9.9,0,0,0,.31-1.31,1,1,0,0,0-1.32-.3,1,1,0,0,0,1,1.61ZM73.24,23a.88.88,0,0,0,.3-1.32,1,1,0,0,0-1.31-.3,1,1,0,0,0-.3,1.31A1,1,0,0,0,73.24,23ZM85.17,59.4a1.09,1.09,0,1,0,1.32-.81A1.13,1.13,0,0,0,85.17,59.4ZM69.4,96.2c-.41-.2-.81.1-1,.61a.83.83,0,1,0,1-.61Zm-45.89-68a.51.51,0,1,0,.2-1c-.3,0-.61.1-.61.4A.45.45,0,0,0,23.51,28.19Zm3.22,50.12c-.41.1-.71.4-.61.81a.69.69,0,0,0,.81.6c.4,0,.61-.4.61-.81A.69.69,0,0,0,26.73,78.31ZM94,44l-.61,2.63L91,47.77l2.62.61,1.12,2.32.6-2.63L97.71,47l-2.63-.61ZM59.79,26.74a1,1,0,0,0-.6,1.41,4.59,4.59,0,0,1,.3,3,1.14,1.14,0,0,0,.91,1.31h.2a1,1,0,0,0,1-.91,6.14,6.14,0,0,0-.4-4.24A1,1,0,0,0,59.79,26.74Zm-.5-4.35a6,6,0,0,0-1-1.52,1.11,1.11,0,0,0-1.52,0,1.09,1.09,0,0,0,0,1.52,4.6,4.6,0,0,1,.61,1,1.18,1.18,0,0,0,1.51.51A1.15,1.15,0,0,0,59.29,22.39ZM97.66,93.14a128,128,0,0,0-6-18.49C89.59,69.43,82.85,63,78.5,59.8A3.16,3.16,0,0,1,78.19,55C82.44,50.9,90,43,92.45,38.87c1.6-2.92,4.75-8.46,4.89-13.26.31-3.57-.18-7.7-4.91-9.59a6.9,6.9,0,0,0-7.14.92c-3,2.06-4,7.7-6.07,13.32-2.44,6.48-6.28,7.3-8.31,7.3s-.7-2.14-5.35-15.59-17-11-26.29-5.44c-11.83,7.07-6.58,22.14-3.64,31.85C34,50,27.74,51.21,22.08,54.24c-3.52,1.89-6.53,3.11-9.47,5.47-4.09,3.29-5.86,7-4.44,12.06a7.22,7.22,0,0,0,3.58,4.09c3.34,1.52,8.26-.69,15.79-6.35A46.19,46.19,0,0,1,39.47,64s4.55,7,8.8,15.27-4.56,11-5.47,11S28,88.92,31.18,100.65s19.92,7.48,28.51,1.82,6.47-24.16,6.47-24.16C74.55,77,77.18,85.89,78,90.44s-1,12.44,7.48,12.64a13.28,13.28,0,0,0,3.54-.51c4.58-1.06,7.23-3.36,8.32-5.81A5.84,5.84,0,0,0,97.66,93.14Zm-42.32-55c-8.59,3.24-12.74-1-13.24-8.79-.61-8.8,7.58-11,7.58-11,9.1-3,11.53,1.31,13.65,7.78S63.84,34.93,55.34,38.16Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
),
|
||||||
|
[ICONS.ODYSEE_DARK_TEXT]: (props: IconProps) => (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
data-name="Layer 1"
|
||||||
|
id="Layer_1"
|
||||||
|
strokeWidth="0"
|
||||||
|
viewBox="0 0 397 119.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<style>
|
||||||
|
{'.cls-1{fill:none;}.cls-2{fill:url(#linear-gradient);}.cls-3{clip-path:url(#clip-path);}.cls-4{fill:#fff;}'}
|
||||||
|
</style>
|
||||||
|
<linearGradient id="linear-gradient" x1="45.6" y1="9.82" x2="88.36" y2="157.76" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0" stopColor="#ef1970" />
|
||||||
|
<stop offset="0.14" stopColor="#f23b5c" />
|
||||||
|
<stop offset="0.45" stopColor="#f77d35" />
|
||||||
|
<stop offset="0.7" stopColor="#fcad18" />
|
||||||
|
<stop offset="0.89" stopColor="#fecb07" />
|
||||||
|
<stop offset="1" stopColor="#ffd600" />
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath id="clip-path">
|
||||||
|
<rect className="cls-1" x="8.45" y="8.03" width="103.05" height="103.05" rx="51.52" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<path d="M216,36.55A105.13,105.13,0,0,0,214.51,25c-.21-1.11-.45-2.47-.78-4.44s-.61-3.46-.83-4.51-.45-2-.68-2.85A5,5,0,0,0,211,10.74a4.62,4.62,0,0,0-1.61-1,6.27,6.27,0,0,0-2-.28c-.78,0-3.16,0-4.16,1.74-.39.67-.74,1.81-.74,5.57a14.41,14.41,0,0,0,.14,2.48l.14,1.12a40.39,40.39,0,0,0,.89,5.22,2.86,2.86,0,0,0,.12.35,11.3,11.3,0,0,0,.15,1.36,12.27,12.27,0,0,0,.56,2.47,6.14,6.14,0,0,1,.3,1.78c.48,5.45.35,6.88.3,7.28a1.07,1.07,0,0,1-.48.07c-1.4,0-15.06,4-18.61,6.36a22.12,22.12,0,0,0-7.78,8C176.52,56.48,176,74.82,176,75c-.09,4.22.64,6.82,2.27,8.14l.32.35a18.94,18.94,0,0,0,11.85,6.2,88.44,88.44,0,0,0,14.48.73c1.79,0,3.48,0,5.06,0h.3l7.36-2.4-.24-14C217.36,67.55,216.89,46.57,216,36.55ZM207.2,74.16c-.11.88-.2,1.55-.27,2a4.85,4.85,0,0,1-.28,1c-.07.17-.13.29-.14.33l-.24.1a2.82,2.82,0,0,1-.8.15c-.42,0-1,0-1.84,0a45.33,45.33,0,0,1-9.91-1.43,30.77,30.77,0,0,1-5.88-1.77h0c-.8-1.88,1.22-16,6.72-20.09s8.27-4.54,9.65-4.11c.38.12,1.54.48,2.33,3,.2,1,.41,7.6.52,11.15.08,2.47.14,4.51.19,5.14A22.23,22.23,0,0,1,207.2,74.16Z" />
|
||||||
|
<path d="M251.17,34.44A8.26,8.26,0,0,0,248.7,38l0,.06a41,41,0,0,1-2.6,5.89,10.94,10.94,0,0,0-1.38,4.79A4.41,4.41,0,0,1,244.4,50a5.3,5.3,0,0,1-.55,1.17l-.44-.28a26.83,26.83,0,0,1-2.5-2.09c-1-1-2.35-2.29-4-4-7.07-7.19-11.28-9.75-14.07-8.62-1.59.65-2.4,2.31-2.4,4.94,0,1.63.85,3.69,2.61,6.27a96.53,96.53,0,0,0,7.64,9.36c5.21,5.9,8.73,7.54,10.36,8.23a21.38,21.38,0,0,1-.37,4.4,45.35,45.35,0,0,1-1.89,5.06,42,42,0,0,0-2.5,6.39,20.24,20.24,0,0,0-1.06,5.49c0,2.11.3,3.41,1,4.22a3.19,3.19,0,0,0,2.57,1.06,5.87,5.87,0,0,0,1.21-.13,7.75,7.75,0,0,0,3-1.1,5.46,5.46,0,0,0,2.12-2.15c.18-.34.58-1.13,1.19-2.37s1-2.08,1.24-2.56a25,25,0,0,0,1.92-5.43c.7-2.58,1.34-5.32,1.88-8.11s1.44-6,2.48-9.67,2-6.73,2.85-9.09c1.16-3.07,2-5.52,2.56-7.5a19.84,19.84,0,0,0,.88-5.21,5.07,5.07,0,0,0-1.35-3.85C257,32.86,253.27,32.86,251.17,34.44Z" />
|
||||||
|
<path d="M296.7,35.06a3.39,3.39,0,0,0-1.31-.87A5.37,5.37,0,0,0,294,33.8c-.33,0-.87-.08-1.61-.12s-1.39-.06-2-.08-1.56,0-2.75,0c-6,0-10.18.83-12.84,2.55a17.31,17.31,0,0,0-7.18,8.16c-1.41,3.3-2.13,7.74-2.13,13.17l-.12,10.68,11,3.6c3.51,1.15,5.37,1.87,6.35,2.3a15.28,15.28,0,0,1-2.6.73,24.58,24.58,0,0,1-5.24.57,38,38,0,0,0-4.87.21A4.88,4.88,0,0,0,267,76.75a4,4,0,0,0-1,2.93A5.37,5.37,0,0,0,268.22,84a11.22,11.22,0,0,0,4.94,2,26.55,26.55,0,0,0,4.73.4l1.2,0a25.46,25.46,0,0,0,6.49-1.14,20.68,20.68,0,0,0,5.84-2.8,13.33,13.33,0,0,0,3.76-3.92,10.08,10.08,0,0,0,1.06-5,9,9,0,0,0-3.14-7.37c-1.87-1.5-5.33-3-10.56-4.44-5.54-1.67-6.51-2.49-6.7-2.71s-.7-1.29.68-4.65a23.14,23.14,0,0,1,5.14-7.64c2.55-2.54,3.78-3.27,4.28-3.48s1.66-.46,4.33-.08c1,.15,1.77.25,2.27.3a9.47,9.47,0,0,0,1.76,0,4.44,4.44,0,0,0,1.61-.37,2.83,2.83,0,0,0,1.24-1.33,4,4,0,0,0,.42-1.58c0-.35,0-.87,0-1.57V37.65a4,4,0,0,0-.26-1.4A3.59,3.59,0,0,0,296.7,35.06Z" />
|
||||||
|
<path d="M341.77,41.73a8.9,8.9,0,0,0-1-1.91,13,13,0,0,0-1.64-2l-1.61-1.68a19.65,19.65,0,0,0-5.45-4.2,16.56,16.56,0,0,0-6.49-1,19.81,19.81,0,0,0-11.31,3.24h0a30.8,30.8,0,0,0-6.52,5.73,17.93,17.93,0,0,0-3.4,6.7,45.67,45.67,0,0,0-1.29,9.6c-.57,10.37,1.22,18.06,5.31,22.88,3.78,4.44,9.71,6.69,17.69,6.69.81,0,1.64,0,2.49-.07l3.38-.25a21.33,21.33,0,0,0,2.43-.32,7.45,7.45,0,0,0,2-.56,3.81,3.81,0,0,0,1.33-1.14,3.5,3.5,0,0,0,.74-1.75,14.71,14.71,0,0,0,.07-1.59c0-1.39-.17-3.34-1.63-4.21-.67-.39-1.77-.68-5.28-.24a16.13,16.13,0,0,1-9-1.7,13.27,13.27,0,0,1-6.38-5.67l-.84-1.58,5.84-.64a34.24,34.24,0,0,0,8-1.56,27.41,27.41,0,0,0,6.56-3.33c1.4-1,2.42-1.75,3.07-2.31a8.54,8.54,0,0,0,2-2.56,9.49,9.49,0,0,0,1.05-3.07c.13-.87.26-2.23.37-4.08q.12-1.87.12-3a18.62,18.62,0,0,0-.15-2.37A11.51,11.51,0,0,0,341.77,41.73ZM316.33,53.11l-1.68-1.74,4.24-4.11A32,32,0,0,1,323,43.63a20.31,20.31,0,0,1,2-1.27,5,5,0,0,1,1.52.92,18.22,18.22,0,0,1,2.93,2.8l2.54,3-2.26,2a14.46,14.46,0,0,1-3.48,2.14,17.43,17.43,0,0,1-4,1.4,9.45,9.45,0,0,1-3.66.14A5.19,5.19,0,0,1,316.33,53.11Z" />
|
||||||
|
<path d="M387.35,46.9a10.38,10.38,0,0,0-.43-2,7.76,7.76,0,0,0-1-1.92,12.53,12.53,0,0,0-1.42-1.8l-1.82-1.91a19.86,19.86,0,0,0-5.46-4.2,16.66,16.66,0,0,0-6.48-1,19.84,19.84,0,0,0-11.32,3.24h0A31.34,31.34,0,0,0,352.91,43a18.23,18.23,0,0,0-3.4,6.7,45.1,45.1,0,0,0-1.28,9.6c-.57,10.37,1.21,18.07,5.31,22.88,3.77,4.44,9.71,6.69,17.68,6.69.81,0,1.64,0,2.49-.07l3.39-.25a19.3,19.3,0,0,0,2.43-.32,7.71,7.71,0,0,0,2-.55,3.82,3.82,0,0,0,1.34-1.14,3.54,3.54,0,0,0,.74-1.76,14.71,14.71,0,0,0,.07-1.59c0-1.39-.17-3.34-1.64-4.21-.67-.39-1.77-.68-5.27-.24a16.09,16.09,0,0,1-9-1.7,13.29,13.29,0,0,1-6.37-5.67l-.85-1.57,5.85-.65a34.15,34.15,0,0,0,8-1.56,27.23,27.23,0,0,0,6.56-3.33c1.4-1,2.43-1.75,3.07-2.3a8.82,8.82,0,0,0,2-2.56,9.87,9.87,0,0,0,1-3.08c.13-.87.26-2.23.37-4.08.08-1.25.11-2.24.11-3A18.62,18.62,0,0,0,387.35,46.9Zm-25.86,9.34-1.68-1.74L364,50.39a33.45,33.45,0,0,1,4.15-3.63,18.65,18.65,0,0,1,2-1.26,5,5,0,0,1,1.52.91,18.17,18.17,0,0,1,2.92,2.8l2.55,3-2.27,2a15.16,15.16,0,0,1-3.47,2.14,17.83,17.83,0,0,1-4,1.39,9.23,9.23,0,0,1-3.66.14A5.08,5.08,0,0,1,361.49,56.24Z" />
|
||||||
|
<path d="M135.65,41.29a21.51,21.51,0,0,1,5.44-1,82,82,0,0,1,8.25-.4c4.56,0,7.65.16,9.28.62A14.23,14.23,0,0,1,164.13,44a16.32,16.32,0,0,1,3.68,5.32,31.66,31.66,0,0,1,1.73,8.12,48.43,48.43,0,0,1-.46,15.29q-1.43,7.38-4.3,9a60,60,0,0,0-7.43,5.2,13.3,13.3,0,0,1-5,2.69,22.19,22.19,0,0,1-6.71-.09,23.84,23.84,0,0,1-7.13-2.26A28.75,28.75,0,0,1,132,82.05q-1.89-1.86-2.7-2.7a14.72,14.72,0,0,1-1.73-2.23A11.59,11.59,0,0,1,126.4,75a15.75,15.75,0,0,1-.56-2.61,22.94,22.94,0,0,1-.29-3.4V64.15Q125.55,45.13,135.65,41.29Zm20,8.79q-4.53-4.3-5.66-4.3c-1.62,0-3.68,1-6.19,2.83a25.06,25.06,0,0,0-6.07,6.2q-3.8,5.53-3.42,10t5.1,9.61l5.23,5.67,6.41-2.93A17.64,17.64,0,0,0,159.5,70a14.09,14.09,0,0,0,1.71-10A18.78,18.78,0,0,0,155.67,50.08Z" />
|
||||||
|
<rect className="cls-2" x="8.45" y="8.03" width="103.05" height="103.05" rx="51.52" />
|
||||||
|
<g className="cls-3">
|
||||||
|
<path
|
||||||
|
className="cls-4"
|
||||||
|
d="M17.12,48.17a.9.9,0,0,0,.31-1.31,1,1,0,0,0-1.32-.3,1,1,0,0,0,1,1.61ZM73.24,23a.88.88,0,0,0,.3-1.32,1,1,0,0,0-1.31-.3,1,1,0,0,0-.3,1.31A1,1,0,0,0,73.24,23ZM85.17,59.4a1.09,1.09,0,1,0,1.32-.81A1.13,1.13,0,0,0,85.17,59.4ZM69.4,96.2c-.41-.2-.81.1-1,.61a.83.83,0,1,0,1-.61Zm-45.89-68a.51.51,0,1,0,.2-1c-.3,0-.61.1-.61.4A.45.45,0,0,0,23.51,28.19Zm3.22,50.12c-.41.1-.71.4-.61.81a.69.69,0,0,0,.81.6c.4,0,.61-.4.61-.81A.69.69,0,0,0,26.73,78.31ZM94,44l-.61,2.63L91,47.77l2.62.61,1.12,2.32.6-2.63L97.71,47l-2.63-.61ZM59.29,22.39a6,6,0,0,0-1-1.52,1.11,1.11,0,0,0-1.52,0,1.09,1.09,0,0,0,0,1.52,4.6,4.6,0,0,1,.61,1,1.18,1.18,0,0,0,1.51.51A1.15,1.15,0,0,0,59.29,22.39Zm.5,4.35a1,1,0,0,0-.6,1.41,4.59,4.59,0,0,1,.3,3,1.14,1.14,0,0,0,.91,1.31h.2a1,1,0,0,0,1-.91,6.14,6.14,0,0,0-.4-4.24A1,1,0,0,0,59.79,26.74Zm37.87,66.4a128,128,0,0,0-6-18.49C89.59,69.43,82.85,63,78.5,59.8A3.16,3.16,0,0,1,78.19,55C82.44,50.9,90,43,92.45,38.87c1.6-2.92,4.75-8.46,4.89-13.26.31-3.57-.18-7.7-4.91-9.59a6.9,6.9,0,0,0-7.14.92c-3,2.06-4,7.7-6.07,13.32-2.44,6.48-6.28,7.3-8.31,7.3s-.7-2.14-5.35-15.59-17-11-26.29-5.44c-11.83,7.07-6.58,22.14-3.64,31.85C34,50,27.74,51.21,22.08,54.24c-3.52,1.89-6.53,3.11-9.47,5.47-4.09,3.29-5.86,7-4.44,12.06a7.22,7.22,0,0,0,3.58,4.09c3.34,1.52,8.26-.69,15.79-6.35A46.19,46.19,0,0,1,39.47,64s4.55,7,8.8,15.27-4.56,11-5.47,11S28,88.92,31.18,100.65s19.92,7.48,28.51,1.82,6.47-24.16,6.47-24.16C74.55,77,77.18,85.89,78,90.44s-1,12.44,7.48,12.64a13.28,13.28,0,0,0,3.54-.51c4.58-1.06,7.23-3.36,8.32-5.81A5.84,5.84,0,0,0,97.66,93.14Zm-42.32-55c-8.59,3.24-12.74-1-13.24-8.79-.61-8.8,7.58-11,7.58-11,9.1-3,11.53,1.31,13.65,7.78S63.84,34.93,55.34,38.16Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
[ICONS.LBC]: (props: IconProps) => {
|
[ICONS.LBC]: (props: IconProps) => {
|
||||||
|
|
|
@ -1,18 +1,30 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Node } from 'react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReachTooltip from '@reach/tooltip';
|
import MUITooltip from '@mui/material/Tooltip';
|
||||||
// import '@reach/tooltip/styles.css'; --> 'scss/third-party.scss'
|
import type { Node } from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label: string | Node,
|
arrow?: boolean,
|
||||||
children: Node,
|
children: Node,
|
||||||
|
disableInteractive?: boolean,
|
||||||
|
enterDelay?: number,
|
||||||
|
title?: string | Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
function Tooltip(props: Props) {
|
function Tooltip(props: Props) {
|
||||||
const { children, label } = props;
|
const { arrow = true, children, disableInteractive = true, enterDelay = 300, title } = props;
|
||||||
|
|
||||||
return <ReachTooltip label={label}>{children}</ReachTooltip>;
|
return (
|
||||||
|
<MUITooltip
|
||||||
|
arrow={arrow}
|
||||||
|
disableInteractive={disableInteractive}
|
||||||
|
enterDelay={enterDelay}
|
||||||
|
enterNextDelay={enterDelay}
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</MUITooltip>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Tooltip;
|
export default Tooltip;
|
||||||
|
|
|
@ -18,6 +18,11 @@ import { useHistory } from 'react-router';
|
||||||
import { isURIEqual } from 'util/lbryURI';
|
import { isURIEqual } from 'util/lbryURI';
|
||||||
import AutoplayCountdown from 'component/autoplayCountdown';
|
import AutoplayCountdown from 'component/autoplayCountdown';
|
||||||
|
|
||||||
|
// scss/init/vars.scss
|
||||||
|
// --header-height
|
||||||
|
const HEADER_HEIGHT = 64;
|
||||||
|
const HEADER_HEIGHT_MOBILE = 56;
|
||||||
|
|
||||||
const IS_DESKTOP_MAC = typeof process === 'object' ? process.platform === 'darwin' : false;
|
const IS_DESKTOP_MAC = typeof process === 'object' ? process.platform === 'darwin' : false;
|
||||||
const DEBOUNCE_WINDOW_RESIZE_HANDLER_MS = 100;
|
const DEBOUNCE_WINDOW_RESIZE_HANDLER_MS = 100;
|
||||||
export const INLINE_PLAYER_WRAPPER_CLASS = 'inline-player__wrapper';
|
export const INLINE_PLAYER_WRAPPER_CLASS = 'inline-player__wrapper';
|
||||||
|
@ -339,8 +344,11 @@ export default function FileRenderFloating(props: Props) {
|
||||||
width: fileViewerRect.width,
|
width: fileViewerRect.width,
|
||||||
height: fileViewerRect.height,
|
height: fileViewerRect.height,
|
||||||
left: fileViewerRect.x,
|
left: fileViewerRect.x,
|
||||||
// 80px is header height in scss/init/vars.scss
|
top:
|
||||||
top: fileViewerRect.windowOffset + fileViewerRect.top - 80 - (IS_DESKTOP_MAC ? 24 : 0),
|
fileViewerRect.windowOffset +
|
||||||
|
fileViewerRect.top -
|
||||||
|
(isMobile ? HEADER_HEIGHT_MOBILE : HEADER_HEIGHT) -
|
||||||
|
(IS_DESKTOP_MAC ? 24 : 0),
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,31 @@
|
||||||
import * as SETTINGS from 'constants/settings';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { selectTotalBalance, selectBalance } from 'redux/selectors/wallet';
|
|
||||||
import { formatCredits } from 'util/format-credits';
|
|
||||||
import { selectGetSyncErrorMessage } from 'redux/selectors/sync';
|
|
||||||
import { selectUserVerifiedEmail, selectUserEmail, selectEmailToVerify, selectUser } from 'redux/selectors/user';
|
|
||||||
import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user';
|
import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
|
||||||
import { doSignOut, doOpenModal } from 'redux/actions/app';
|
import { doSignOut, doOpenModal } from 'redux/actions/app';
|
||||||
import { selectClientSetting, selectLanguage } from 'redux/selectors/settings';
|
import { selectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectHasNavigated, selectActiveChannelClaim, selectActiveChannelStakedLevel } from 'redux/selectors/app';
|
import { selectGetSyncErrorMessage } from 'redux/selectors/sync';
|
||||||
|
import { selectHasNavigated } from 'redux/selectors/app';
|
||||||
|
import { selectTotalBalance, selectBalance } from 'redux/selectors/wallet';
|
||||||
|
import { selectUserVerifiedEmail, selectEmailToVerify, selectUser } from 'redux/selectors/user';
|
||||||
|
import * as MODALS from 'constants/modal_types';
|
||||||
|
import * as SETTINGS from 'constants/settings';
|
||||||
import Header from './view';
|
import Header from './view';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
language: selectLanguage(state),
|
|
||||||
balance: selectBalance(state),
|
|
||||||
roundedSpendableBalance: formatCredits(selectBalance(state), 2, true),
|
|
||||||
roundedBalance: formatCredits(selectTotalBalance(state), 2, true),
|
|
||||||
currentTheme: selectClientSetting(state, SETTINGS.THEME),
|
|
||||||
automaticDarkModeEnabled: selectClientSetting(state, SETTINGS.AUTOMATIC_DARK_MODE_ENABLED),
|
|
||||||
hideBalance: selectClientSetting(state, SETTINGS.HIDE_BALANCE),
|
|
||||||
authenticated: selectUserVerifiedEmail(state),
|
authenticated: selectUserVerifiedEmail(state),
|
||||||
email: selectUserEmail(state),
|
balance: selectBalance(state),
|
||||||
syncError: selectGetSyncErrorMessage(state),
|
|
||||||
emailToVerify: selectEmailToVerify(state),
|
emailToVerify: selectEmailToVerify(state),
|
||||||
hasNavigated: selectHasNavigated(state),
|
hasNavigated: selectHasNavigated(state),
|
||||||
|
hideBalance: selectClientSetting(state, SETTINGS.HIDE_BALANCE),
|
||||||
|
totalBalance: selectTotalBalance(state),
|
||||||
|
syncError: selectGetSyncErrorMessage(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
activeChannelClaim: selectActiveChannelClaim(state),
|
|
||||||
activeChannelStakedLevel: selectActiveChannelStakedLevel(state),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
setClientSetting: (key, value, push) => dispatch(doSetClientSetting(key, value, push)),
|
|
||||||
signOut: () => dispatch(doSignOut()),
|
|
||||||
doOpenModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
|
||||||
clearEmailEntry: () => dispatch(doClearEmailEntry()),
|
clearEmailEntry: () => dispatch(doClearEmailEntry()),
|
||||||
clearPasswordEntry: () => dispatch(doClearPasswordEntry()),
|
clearPasswordEntry: () => dispatch(doClearPasswordEntry()),
|
||||||
|
signOut: () => dispatch(doSignOut()),
|
||||||
|
openChangelog: (modalProps) => dispatch(doOpenModal(MODALS.CONFIRM, modalProps)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(Header);
|
export default connect(select, perform)(Header);
|
||||||
|
|
|
@ -1,50 +1,24 @@
|
||||||
// @flow
|
// @flow
|
||||||
import { ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM, ENABLE_UI_NOTIFICATIONS } from 'config';
|
import 'scss/component/_header.scss';
|
||||||
import * as ICONS from 'constants/icons';
|
|
||||||
import * as MODALS from 'constants/modal_types';
|
import { formatCredits } from 'util/format-credits';
|
||||||
import * as SETTINGS from 'constants/settings';
|
|
||||||
import * as PAGES from 'constants/pages';
|
|
||||||
import React from 'react';
|
|
||||||
import { withRouter } from 'react-router';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import WunderBar from 'component/wunderbar';
|
|
||||||
import Icon from 'component/common/icon';
|
|
||||||
import { Menu, MenuList, MenuButton, MenuItem, MenuLink } from '@reach/menu-button';
|
|
||||||
import NavigationButton from 'component/navigationButton';
|
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
import NotificationBubble from 'component/notificationBubble';
|
import { withRouter } from 'react-router';
|
||||||
import NotificationHeaderButton from 'component/notificationHeaderButton';
|
import * as ICONS from 'constants/icons';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import * as PAGES from 'constants/pages';
|
||||||
import SkipNavigationButton from 'component/skipNavigationButton';
|
import Button from 'component/button';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import HeaderMenuButtons from 'component/headerMenuButtons';
|
||||||
|
import HeaderProfileMenuButton from 'component/headerProfileMenuButton';
|
||||||
import Logo from 'component/logo';
|
import Logo from 'component/logo';
|
||||||
// @if TARGET='app'
|
import NotificationBubble from 'component/notificationBubble';
|
||||||
import { remote } from 'electron';
|
import React from 'react';
|
||||||
import { IS_MAC } from 'component/app/view';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
// @endif
|
import SkipNavigationButton from 'component/skipNavigationButton';
|
||||||
|
import Tooltip from 'component/common/tooltip';
|
||||||
|
import WunderBar from 'component/wunderbar';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
user: ?User,
|
|
||||||
balance: string,
|
|
||||||
balance: number,
|
|
||||||
roundedBalance: string,
|
|
||||||
roundedSpendableBalance: string,
|
|
||||||
history: {
|
|
||||||
entities: {}[],
|
|
||||||
goBack: () => void,
|
|
||||||
goForward: () => void,
|
|
||||||
index: number,
|
|
||||||
length: number,
|
|
||||||
location: { pathname: string },
|
|
||||||
push: (string) => void,
|
|
||||||
replace: (string) => void,
|
|
||||||
},
|
|
||||||
currentTheme: string,
|
|
||||||
automaticDarkModeEnabled: boolean,
|
|
||||||
setClientSetting: (string, boolean | string, ?boolean) => void,
|
|
||||||
hideBalance: boolean,
|
|
||||||
email: ?string,
|
|
||||||
authenticated: boolean,
|
authenticated: boolean,
|
||||||
authHeader: boolean,
|
authHeader: boolean,
|
||||||
backout: {
|
backout: {
|
||||||
|
@ -53,220 +27,191 @@ type Props = {
|
||||||
title: string,
|
title: string,
|
||||||
simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile
|
simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile
|
||||||
},
|
},
|
||||||
syncError: ?string,
|
balance: number,
|
||||||
emailToVerify?: string,
|
emailToVerify?: string,
|
||||||
signOut: () => void,
|
hasNavigated: boolean,
|
||||||
doOpenModal: (string, ?{}) => void,
|
hideBalance: boolean,
|
||||||
|
hideCancel: boolean,
|
||||||
|
history: {
|
||||||
|
goBack: () => void,
|
||||||
|
location: { pathname: string },
|
||||||
|
push: (string) => void,
|
||||||
|
replace: (string) => void,
|
||||||
|
},
|
||||||
|
isAbsoluteSideNavHidden: boolean,
|
||||||
|
sidebarOpen: boolean,
|
||||||
|
syncError: ?string,
|
||||||
|
totalBalance?: number,
|
||||||
|
user: ?User,
|
||||||
clearEmailEntry: () => void,
|
clearEmailEntry: () => void,
|
||||||
clearPasswordEntry: () => void,
|
clearPasswordEntry: () => void,
|
||||||
hasNavigated: boolean,
|
openChangelog: ({}) => void,
|
||||||
sidebarOpen: boolean,
|
|
||||||
setSidebarOpen: (boolean) => void,
|
setSidebarOpen: (boolean) => void,
|
||||||
isAbsoluteSideNavHidden: boolean,
|
signOut: () => void,
|
||||||
hideCancel: boolean,
|
|
||||||
activeChannelClaim: ?ChannelClaim,
|
|
||||||
activeChannelStakedLevel: number,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Header = (props: Props) => {
|
const Header = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
balance,
|
|
||||||
roundedBalance,
|
|
||||||
roundedSpendableBalance,
|
|
||||||
history,
|
|
||||||
setClientSetting,
|
|
||||||
currentTheme,
|
|
||||||
automaticDarkModeEnabled,
|
|
||||||
hideBalance,
|
|
||||||
email,
|
|
||||||
authenticated,
|
authenticated,
|
||||||
authHeader,
|
authHeader,
|
||||||
signOut,
|
backout,
|
||||||
|
balance,
|
||||||
|
emailToVerify,
|
||||||
|
hideBalance,
|
||||||
|
hideCancel,
|
||||||
|
history,
|
||||||
|
isAbsoluteSideNavHidden,
|
||||||
|
sidebarOpen,
|
||||||
syncError,
|
syncError,
|
||||||
doOpenModal,
|
totalBalance,
|
||||||
|
user,
|
||||||
clearEmailEntry,
|
clearEmailEntry,
|
||||||
clearPasswordEntry,
|
clearPasswordEntry,
|
||||||
emailToVerify,
|
openChangelog,
|
||||||
backout,
|
|
||||||
sidebarOpen,
|
|
||||||
setSidebarOpen,
|
setSidebarOpen,
|
||||||
isAbsoluteSideNavHidden,
|
signOut,
|
||||||
hideCancel,
|
|
||||||
user,
|
|
||||||
activeChannelClaim,
|
|
||||||
activeChannelStakedLevel,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const {
|
||||||
|
location: { pathname },
|
||||||
|
goBack,
|
||||||
|
push,
|
||||||
|
} = history;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
// on the verify page don't let anyone escape other than by closing the tab to keep session data consistent
|
// on the verify page don't let anyone escape other than by closing the tab to keep session data consistent
|
||||||
const isVerifyPage = history.location.pathname.includes(PAGES.AUTH_VERIFY);
|
const isVerifyPage = pathname.includes(PAGES.AUTH_VERIFY);
|
||||||
const isSignUpPage = history.location.pathname.includes(PAGES.AUTH);
|
const isSignUpPage = pathname.includes(PAGES.AUTH);
|
||||||
const isSignInPage = history.location.pathname.includes(PAGES.AUTH_SIGNIN);
|
const isSignInPage = pathname.includes(PAGES.AUTH_SIGNIN);
|
||||||
const isPwdResetPage = history.location.pathname.includes(PAGES.AUTH_PASSWORD_RESET);
|
const isPwdResetPage = pathname.includes(PAGES.AUTH_PASSWORD_RESET);
|
||||||
const hasBackout = Boolean(backout);
|
const iYTSyncPage = pathname.includes(PAGES.YOUTUBE_SYNC);
|
||||||
|
|
||||||
|
// For pages that allow for "backing out", shows a backout option instead of the Home logo
|
||||||
|
const canBackout = Boolean(backout);
|
||||||
const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {};
|
const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {};
|
||||||
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
|
||||||
const livestreamEnabled = Boolean(
|
const balanceLoading = totalBalance === undefined;
|
||||||
ENABLE_NO_SOURCE_CLAIMS &&
|
const roundedSpendableBalance = formatCredits(balance, 2, true);
|
||||||
user &&
|
const roundedTotalBalance = formatCredits(totalBalance, 2, true);
|
||||||
!user.odysee_live_disabled &&
|
|
||||||
(activeChannelStakedLevel >= CHANNEL_STAKED_LEVEL_LIVESTREAM || user.odysee_live_enabled)
|
|
||||||
);
|
|
||||||
const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url;
|
|
||||||
|
|
||||||
// Sign out if they click the "x" when they are on the password prompt
|
// Sign out if they click the "x" when they are on the password prompt
|
||||||
const authHeaderAction = syncError ? { onClick: signOut } : { navigate: '/' };
|
const authHeaderAction = syncError && { onClick: signOut };
|
||||||
const homeButtonNavigationProps = isVerifyPage ? {} : authHeader ? authHeaderAction : { navigate: '/' };
|
const homeButtonNavigationProps = (isVerifyPage && {}) || (authHeader && authHeaderAction) || { navigate: '/' };
|
||||||
const closeButtonNavigationProps = {
|
const sidebarLabel = sidebarOpen
|
||||||
onClick: () => {
|
? __('Close sidebar - hide channels you are following.')
|
||||||
clearEmailEntry();
|
: __('Expand sidebar - view channels you are following.');
|
||||||
clearPasswordEntry();
|
|
||||||
|
|
||||||
if (syncError) {
|
const onBackout = React.useCallback(
|
||||||
signOut();
|
(e: any) => {
|
||||||
}
|
const { hasNavigated } = props;
|
||||||
|
const { replace } = history;
|
||||||
|
|
||||||
if (isSignInPage && !emailToVerify) {
|
window.removeEventListener('popstate', onBackout);
|
||||||
history.goBack();
|
|
||||||
} else if (isSignUpPage) {
|
if (e.type !== 'popstate') {
|
||||||
history.goBack();
|
// if not initiated by pop (back button)
|
||||||
} else if (isPwdResetPage) {
|
if (hasNavigated && !backNavDefault) {
|
||||||
history.goBack();
|
goBack();
|
||||||
} else {
|
} else {
|
||||||
history.push('/');
|
replace(backNavDefault || `/`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
[backNavDefault, goBack, history, props]
|
||||||
|
);
|
||||||
function onBackout(e) {
|
|
||||||
const { history, hasNavigated } = props;
|
|
||||||
const { goBack, replace } = history;
|
|
||||||
|
|
||||||
window.removeEventListener('popstate', onBackout);
|
|
||||||
|
|
||||||
if (e.type !== 'popstate') {
|
|
||||||
// if not initiated by pop (back button)
|
|
||||||
if (hasNavigated && !backNavDefault) {
|
|
||||||
goBack();
|
|
||||||
} else {
|
|
||||||
replace(backNavDefault || `/`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (hasBackout) {
|
if (canBackout) {
|
||||||
window.addEventListener('popstate', onBackout);
|
window.addEventListener('popstate', onBackout);
|
||||||
return () => window.removeEventListener('popstate', onBackout);
|
return () => window.removeEventListener('popstate', onBackout);
|
||||||
}
|
}
|
||||||
}, [hasBackout]);
|
}, [canBackout, onBackout]);
|
||||||
|
|
||||||
function handleThemeToggle() {
|
const userButtons = (hideWallet?: boolean, hideProfile?: boolean) => (
|
||||||
if (automaticDarkModeEnabled) {
|
<div className="header__menu--right">
|
||||||
setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false);
|
{isMobile && !authHeader && !canBackout && <WunderBar />}
|
||||||
}
|
|
||||||
|
|
||||||
if (currentTheme === 'dark') {
|
{authenticated ? (
|
||||||
setClientSetting(SETTINGS.THEME, 'light', true);
|
<>
|
||||||
} else {
|
{!hideWallet && (
|
||||||
setClientSetting(SETTINGS.THEME, 'dark', true);
|
<Tooltip
|
||||||
}
|
title={
|
||||||
}
|
balance > 0
|
||||||
|
? __('Immediately spendable: %spendable_balance%', { spendable_balance: roundedSpendableBalance })
|
||||||
|
: __('Your Wallet')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{balanceLoading ? (
|
||||||
|
<Skeleton variant="text" animation="wave" className="header__navigationItem--balanceLoading" />
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
navigate={`/$/${PAGES.WALLET}`}
|
||||||
|
className="button--file-action header__navigationItem--balance"
|
||||||
|
label={
|
||||||
|
hideBalance || Number(roundedTotalBalance) === 0
|
||||||
|
? isMobile
|
||||||
|
? __('Wallet')
|
||||||
|
: __('Your Wallet')
|
||||||
|
: roundedTotalBalance
|
||||||
|
}
|
||||||
|
icon={ICONS.LBC}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
const loginButtons = (
|
{!hideProfile && <HeaderProfileMenuButton />}
|
||||||
<div className="header__auth-buttons">
|
</>
|
||||||
<Button
|
) : !isMobile ? (
|
||||||
navigate={`/$/${PAGES.AUTH_SIGNIN}`}
|
<div className="header__authButtons">
|
||||||
button="link"
|
<Button navigate={`/$/${PAGES.AUTH_SIGNIN}`} button="link" label={__('Log In')} disabled={user === null} />
|
||||||
label={__('Log In')}
|
<Button navigate={`/$/${PAGES.AUTH}`} button="primary" label={__('Sign Up')} disabled={user === null} />
|
||||||
className="mobile-hidden"
|
</div>
|
||||||
disabled={user === null}
|
) : (
|
||||||
/>
|
<HeaderProfileMenuButton />
|
||||||
<Button navigate={`/$/${PAGES.AUTH}`} button="primary" label={__('Sign Up')} disabled={user === null} />
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
type BalanceButtonProps = { className: string };
|
|
||||||
const BalanceButton = (balanceButtonProps: BalanceButtonProps) => (
|
|
||||||
<Button
|
|
||||||
title={
|
|
||||||
balance > 0
|
|
||||||
? __('Immediately spendable: %spendable_balance%', { spendable_balance: roundedSpendableBalance })
|
|
||||||
: __('Your Wallet')
|
|
||||||
}
|
|
||||||
navigate={`/$/${PAGES.WALLET}`}
|
|
||||||
className={classnames(balanceButtonProps.className, 'header__navigation-item--balance')}
|
|
||||||
label={hideBalance || Number(roundedBalance) === 0 ? __('Your Wallet') : roundedBalance}
|
|
||||||
icon={ICONS.LBC}
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header className={classnames('header', { 'header--minimal': authHeader })}>
|
||||||
className={classnames('header', {
|
{!authHeader && canBackout ? (
|
||||||
'header--minimal': authHeader,
|
<div className="card__actions--between header__contents">
|
||||||
// @if TARGET='app'
|
<div className="header__menu--left">
|
||||||
'header--mac': IS_MAC,
|
<Button onClick={onBackout} button="link" label={backLabel || __('Cancel')} icon={ICONS.ARROW_LEFT} />
|
||||||
// @endif
|
|
||||||
})}
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
remote.getCurrentWindow().maximize();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
>
|
|
||||||
<div className="header__contents">
|
|
||||||
{!authHeader && backout ? (
|
|
||||||
<div className="card__actions--between">
|
|
||||||
<Button
|
|
||||||
onClick={onBackout}
|
|
||||||
button="link"
|
|
||||||
label={(backLabel && backLabel) || __('Cancel')}
|
|
||||||
icon={ICONS.ARROW_LEFT}
|
|
||||||
/>
|
|
||||||
{backTitle && <h1 className="header__auth-title">{isMobile ? simpleBackTitle || backTitle : backTitle}</h1>}
|
|
||||||
{authenticated || !IS_WEB ? (
|
|
||||||
<BalanceButton className="header__navigation-item menu__title" />
|
|
||||||
) : (
|
|
||||||
loginButtons
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<>
|
{backTitle && <h1 className="header__authTitle">{(isMobile && simpleBackTitle) || backTitle}</h1>}
|
||||||
<div className="header__navigation">
|
|
||||||
|
{userButtons(false, isMobile)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="header__navigation">
|
||||||
|
<div className="header__menu--left">
|
||||||
<SkipNavigationButton />
|
<SkipNavigationButton />
|
||||||
|
|
||||||
{!authHeader && (
|
{!authHeader && (
|
||||||
<span style={{ position: 'relative' }}>
|
<span style={{ position: 'relative' }}>
|
||||||
<Button
|
<Button
|
||||||
aria-label={
|
aria-label={sidebarLabel}
|
||||||
sidebarOpen
|
className="header__navigationItem--icon"
|
||||||
? __('Close sidebar - hide channels you are following.')
|
|
||||||
: __('Expand sidebar - view channels you are following.')
|
|
||||||
}
|
|
||||||
className="header__navigation-item menu__title header__navigation-item--icon"
|
|
||||||
icon={ICONS.MENU}
|
icon={ICONS.MENU}
|
||||||
aria-expanded={sidebarOpen}
|
aria-expanded={sidebarOpen}
|
||||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||||
>
|
>
|
||||||
{isAbsoluteSideNavHidden && isMobile && notificationsEnabled && <NotificationBubble />}
|
{isAbsoluteSideNavHidden && isMobile && <NotificationBubble />}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
aria-label={__('Home')}
|
aria-label={__('Home')}
|
||||||
className="header__navigation-item header__navigation-item--lbry"
|
className="header__navigationItem--logo"
|
||||||
onClick={() => {
|
onClick={() => pathname === '/' && window.location.reload()}
|
||||||
if (history.location.pathname === '/') window.location.reload();
|
|
||||||
}}
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
{...homeButtonNavigationProps}
|
{...homeButtonNavigationProps}
|
||||||
>
|
>
|
||||||
<Logo />
|
<Logo />
|
||||||
|
@ -275,239 +220,63 @@ const Header = (props: Props) => {
|
||||||
{/* @if process.env.DEV_CHANGELOG */}
|
{/* @if process.env.DEV_CHANGELOG */}
|
||||||
{history.location.pathname === '/' && (
|
{history.location.pathname === '/' && (
|
||||||
<Button
|
<Button
|
||||||
title={'Changelog'}
|
title="Changelog"
|
||||||
className="badge--alert"
|
className="badge--alert"
|
||||||
label={'Changelog'}
|
label="Changelog"
|
||||||
icon={ICONS.FEEDBACK}
|
icon={ICONS.FEEDBACK}
|
||||||
onClick={() => {
|
onClick={() =>
|
||||||
doOpenModal(MODALS.CONFIRM, {
|
openChangelog({
|
||||||
title: __('Changelog'),
|
title: __('Changelog'),
|
||||||
subtitle: __('Warning: this is a test instance.'),
|
subtitle: __('Warning: this is a test instance.'),
|
||||||
body: <p style={{ whiteSpace: 'pre-wrap' }}>{process.env.DEV_CHANGELOG}</p>,
|
body: <p style={{ whiteSpace: 'pre-wrap' }}>{process.env.DEV_CHANGELOG}</p>,
|
||||||
onConfirm: (closeModal) => closeModal(),
|
onConfirm: (closeModal) => closeModal(),
|
||||||
hideCancel: true,
|
hideCancel: true,
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
|
|
||||||
{!authHeader && (
|
|
||||||
<div className="header__center">
|
|
||||||
{/* @if TARGET='app' */}
|
|
||||||
{!authHeader && (
|
|
||||||
<div className="header__buttons">
|
|
||||||
<NavigationButton isBackward history={history} />
|
|
||||||
<NavigationButton isBackward={false} history={history} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* @endif */}
|
|
||||||
|
|
||||||
{!authHeader && <WunderBar />}
|
|
||||||
|
|
||||||
<HeaderMenuButtons
|
|
||||||
authenticated={authenticated}
|
|
||||||
notificationsEnabled={notificationsEnabled}
|
|
||||||
history={history}
|
|
||||||
handleThemeToggle={handleThemeToggle}
|
|
||||||
currentTheme={currentTheme}
|
|
||||||
livestreamEnabled={livestreamEnabled}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!authHeader && !backout ? (
|
{!authHeader && !isMobile && (
|
||||||
<div className={classnames('header__menu', { 'header__menu--with-balance': !IS_WEB || authenticated })}>
|
<div className="header__center">
|
||||||
{(!IS_WEB || authenticated) && (
|
<WunderBar />
|
||||||
<BalanceButton className="header__navigation-item menu__title mobile-hidden" />
|
<HeaderMenuButtons />
|
||||||
)}
|
|
||||||
|
|
||||||
{IS_WEB && !authenticated && loginButtons}
|
|
||||||
|
|
||||||
{(authenticated || !IS_WEB) && (
|
|
||||||
<Menu>
|
|
||||||
<MenuButton
|
|
||||||
aria-label={__('Your account')}
|
|
||||||
title={__('Your account')}
|
|
||||||
className={classnames('header__navigation-item', {
|
|
||||||
'menu__title header__navigation-item--icon': !activeChannelUrl,
|
|
||||||
'header__navigation-item--profile-pic': activeChannelUrl,
|
|
||||||
})}
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
>
|
|
||||||
{activeChannelUrl ? (
|
|
||||||
<ChannelThumbnail uri={activeChannelUrl} small noLazyLoad />
|
|
||||||
) : (
|
|
||||||
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
|
|
||||||
)}
|
|
||||||
</MenuButton>
|
|
||||||
<MenuList className="menu__list--header">
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.UPLOADS}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.PUBLISH} />
|
|
||||||
{__('Uploads')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.CHANNELS}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.CHANNEL} />
|
|
||||||
{__('Channels')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.CREATOR_DASHBOARD}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.ANALYTICS} />
|
|
||||||
{__('Creator Analytics')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.REWARDS}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.REWARDS} />
|
|
||||||
{__('Rewards')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.INVITE}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.INVITE} />
|
|
||||||
{__('Invites')}
|
|
||||||
</MenuLink>
|
|
||||||
|
|
||||||
{authenticated ? (
|
|
||||||
<MenuItem onSelect={IS_WEB ? signOut : () => doOpenModal(MODALS.SIGN_OUT)}>
|
|
||||||
<div className="menu__link">
|
|
||||||
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
|
||||||
{__('Sign Out')}
|
|
||||||
</div>
|
|
||||||
<span className="menu__link-help">{email}</span>
|
|
||||||
</MenuItem>
|
|
||||||
) : !IS_WEB ? (
|
|
||||||
<>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.AUTH}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.SIGN_UP} />
|
|
||||||
{__('Sign Up')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.AUTH_SIGNIN}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.SIGN_IN} />
|
|
||||||
{__('Sign In')}
|
|
||||||
</MenuLink>
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
!isVerifyPage &&
|
|
||||||
!hideCancel && (
|
|
||||||
<div className="header__menu">
|
|
||||||
{/* Add an empty span here so we can use the same style as above */}
|
|
||||||
{/* This pushes the close button to the right side */}
|
|
||||||
<span />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
title={__('Go Back')}
|
|
||||||
button="alt"
|
|
||||||
// className="button--header-close"
|
|
||||||
icon={ICONS.REMOVE}
|
|
||||||
{...closeButtonNavigationProps}
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
</>
|
|
||||||
)}
|
{!authHeader && !canBackout
|
||||||
</div>
|
? userButtons(isMobile)
|
||||||
|
: !isVerifyPage &&
|
||||||
|
!hideCancel && (
|
||||||
|
<div className="header__menu--right">
|
||||||
|
<Button
|
||||||
|
title={__('Go Back')}
|
||||||
|
button="alt"
|
||||||
|
// className="button--header-close"
|
||||||
|
icon={ICONS.REMOVE}
|
||||||
|
onClick={() => {
|
||||||
|
if (!iYTSyncPage) {
|
||||||
|
clearEmailEntry();
|
||||||
|
clearPasswordEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncError) signOut();
|
||||||
|
|
||||||
|
if ((isSignInPage && !emailToVerify) || isSignUpPage || isPwdResetPage || iYTSyncPage) {
|
||||||
|
goBack();
|
||||||
|
} else {
|
||||||
|
push('/');
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
type HeaderMenuButtonProps = {
|
|
||||||
authenticated: boolean,
|
|
||||||
notificationsEnabled: boolean,
|
|
||||||
history: { push: (string) => void },
|
|
||||||
handleThemeToggle: (string) => void,
|
|
||||||
currentTheme: string,
|
|
||||||
livestreamEnabled: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
function HeaderMenuButtons(props: HeaderMenuButtonProps) {
|
|
||||||
const { authenticated, notificationsEnabled, handleThemeToggle, currentTheme, livestreamEnabled } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="header__buttons">
|
|
||||||
{(authenticated || !IS_WEB) && (
|
|
||||||
<Menu>
|
|
||||||
<MenuButton
|
|
||||||
aria-label={__('Publish a file, or create a channel')}
|
|
||||||
title={__('Publish a file, or create a channel')}
|
|
||||||
className="header__navigation-item menu__title header__navigation-item--icon mobile-hidden"
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
>
|
|
||||||
<Icon size={18} icon={ICONS.PUBLISH} aria-hidden />
|
|
||||||
</MenuButton>
|
|
||||||
|
|
||||||
<MenuList className="menu__list--header">
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.UPLOAD}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.PUBLISH} />
|
|
||||||
{__('Upload')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.CHANNEL_NEW}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.CHANNEL} />
|
|
||||||
{__('New Channel')}
|
|
||||||
</MenuLink>
|
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.YOUTUBE_SYNC}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.YOUTUBE} />
|
|
||||||
{__('Sync YouTube Channel')}
|
|
||||||
</MenuLink>
|
|
||||||
{/* @endif */}
|
|
||||||
{livestreamEnabled && (
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.LIVESTREAM}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.VIDEO} />
|
|
||||||
{__('Go Live')}
|
|
||||||
</MenuLink>
|
|
||||||
)}
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{notificationsEnabled && <NotificationHeaderButton />}
|
|
||||||
|
|
||||||
<Menu>
|
|
||||||
<MenuButton
|
|
||||||
aria-label={__('Settings')}
|
|
||||||
title={__('Settings')}
|
|
||||||
className="header__navigation-item menu__title header__navigation-item--icon mobile-hidden"
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
>
|
|
||||||
<Icon size={18} icon={ICONS.SETTINGS} aria-hidden />
|
|
||||||
</MenuButton>
|
|
||||||
<MenuList className="menu__list--header">
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.SETTINGS}`}>
|
|
||||||
<Icon aria-hidden tooltip icon={ICONS.SETTINGS} />
|
|
||||||
{__('Settings')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuLink className="menu__link" as={Link} to={`/$/${PAGES.HELP}`}>
|
|
||||||
<Icon aria-hidden icon={ICONS.HELP} />
|
|
||||||
{__('Help')}
|
|
||||||
</MenuLink>
|
|
||||||
<MenuItem className="menu__link" onSelect={handleThemeToggle}>
|
|
||||||
<Icon icon={currentTheme === 'light' ? ICONS.DARK : ICONS.LIGHT} />
|
|
||||||
{currentTheme === 'light' ? __('Dark') : __('Light')}
|
|
||||||
</MenuItem>
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withRouter(Header);
|
export default withRouter(Header);
|
||||||
|
|
24
ui/component/headerMenuButtons/index.js
Normal file
24
ui/component/headerMenuButtons/index.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
|
import { selectActiveChannelStakedLevel } from 'redux/selectors/app';
|
||||||
|
import { selectClientSetting } from 'redux/selectors/settings';
|
||||||
|
import * as SETTINGS from 'constants/settings';
|
||||||
|
import HeaderMenuButtons from './view';
|
||||||
|
import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
|
||||||
|
|
||||||
|
const select = (state) => ({
|
||||||
|
activeChannelStakedLevel: selectActiveChannelStakedLevel(state),
|
||||||
|
authenticated: selectUserVerifiedEmail(state),
|
||||||
|
automaticDarkModeEnabled: selectClientSetting(state, SETTINGS.AUTOMATIC_DARK_MODE_ENABLED),
|
||||||
|
currentTheme: selectClientSetting(state, SETTINGS.THEME),
|
||||||
|
user: selectUser(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
const perform = (dispatch) => ({
|
||||||
|
handleThemeToggle: (automaticDarkModeEnabled, currentTheme) => {
|
||||||
|
if (automaticDarkModeEnabled) dispatch(doSetClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false));
|
||||||
|
dispatch(doSetClientSetting(SETTINGS.THEME, currentTheme === 'dark' ? 'light' : 'dark', true));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(HeaderMenuButtons);
|
81
ui/component/headerMenuButtons/view.jsx
Normal file
81
ui/component/headerMenuButtons/view.jsx
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
// @flow
|
||||||
|
import 'scss/component/_header.scss';
|
||||||
|
|
||||||
|
import { ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
||||||
|
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
|
import HeaderMenuLink from 'component/common/header-menu-link';
|
||||||
|
import Icon from 'component/common/icon';
|
||||||
|
import NotificationHeaderButton from 'component/headerNotificationButton';
|
||||||
|
import React from 'react';
|
||||||
|
import Tooltip from 'component/common/tooltip';
|
||||||
|
|
||||||
|
type HeaderMenuButtonProps = {
|
||||||
|
activeChannelStakedLevel: number,
|
||||||
|
authenticated: boolean,
|
||||||
|
automaticDarkModeEnabled: boolean,
|
||||||
|
currentTheme: string,
|
||||||
|
user: ?User,
|
||||||
|
handleThemeToggle: (boolean, string) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function HeaderMenuButtons(props: HeaderMenuButtonProps) {
|
||||||
|
const {
|
||||||
|
authenticated,
|
||||||
|
automaticDarkModeEnabled,
|
||||||
|
currentTheme,
|
||||||
|
activeChannelStakedLevel,
|
||||||
|
user,
|
||||||
|
handleThemeToggle,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
||||||
|
const livestreamEnabled = Boolean(
|
||||||
|
ENABLE_NO_SOURCE_CLAIMS &&
|
||||||
|
user &&
|
||||||
|
!user.odysee_live_disabled &&
|
||||||
|
(activeChannelStakedLevel >= CHANNEL_STAKED_LEVEL_LIVESTREAM || user.odysee_live_enabled)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="header__buttons">
|
||||||
|
{authenticated && (
|
||||||
|
<Menu>
|
||||||
|
<Tooltip title={__('Publish a file, or create a channel')}>
|
||||||
|
<MenuButton className="header__navigationItem--icon">
|
||||||
|
<Icon size={18} icon={ICONS.PUBLISH} aria-hidden />
|
||||||
|
</MenuButton>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<MenuList className="menu__list--header">
|
||||||
|
<HeaderMenuLink page={PAGES.UPLOAD} icon={ICONS.PUBLISH} name={__('Upload')} />
|
||||||
|
<HeaderMenuLink page={PAGES.CHANNEL_NEW} icon={ICONS.CHANNEL} name={__('New Channel')} />
|
||||||
|
<HeaderMenuLink page={PAGES.YOUTUBE_SYNC} icon={ICONS.YOUTUBE} name={__('Sync YouTube Channel')} />
|
||||||
|
{livestreamEnabled && <HeaderMenuLink page={PAGES.LIVESTREAM} icon={ICONS.VIDEO} name={__('Go Live')} />}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{notificationsEnabled && <NotificationHeaderButton />}
|
||||||
|
|
||||||
|
<Menu>
|
||||||
|
<Tooltip title={__('Settings')}>
|
||||||
|
<MenuButton className="header__navigationItem--icon">
|
||||||
|
<Icon size={18} icon={ICONS.SETTINGS} aria-hidden />
|
||||||
|
</MenuButton>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<MenuList className="menu__list--header">
|
||||||
|
<HeaderMenuLink page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||||
|
<HeaderMenuLink page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||||
|
|
||||||
|
<MenuItem className="menu__link" onSelect={() => handleThemeToggle(automaticDarkModeEnabled, currentTheme)}>
|
||||||
|
<Icon icon={currentTheme === 'light' ? ICONS.DARK : ICONS.LIGHT} />
|
||||||
|
{currentTheme === 'light' ? __('Dark') : __('Light')}
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,16 +1,10 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import { selectUnseenNotificationCount } from 'redux/selectors/notifications';
|
||||||
selectNotifications,
|
|
||||||
selectIsFetchingNotifications,
|
|
||||||
selectUnseenNotificationCount,
|
|
||||||
} from 'redux/selectors/notifications';
|
|
||||||
import { doSeeAllNotifications } from 'redux/actions/notifications';
|
import { doSeeAllNotifications } from 'redux/actions/notifications';
|
||||||
import { selectUser } from 'redux/selectors/user';
|
import { selectUser } from 'redux/selectors/user';
|
||||||
import NotificationHeaderButton from './view';
|
import NotificationHeaderButton from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = (state) => ({
|
||||||
notifications: selectNotifications(state),
|
|
||||||
fetching: selectIsFetchingNotifications(state),
|
|
||||||
unseenCount: selectUnseenNotificationCount(state),
|
unseenCount: selectUnseenNotificationCount(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
|
@ -1,51 +1,41 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as PAGES from 'constants/pages';
|
import 'scss/component/_header.scss';
|
||||||
|
|
||||||
|
import { ENABLE_UI_NOTIFICATIONS } from 'config';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import React from 'react';
|
import * as PAGES from 'constants/pages';
|
||||||
|
import Button from 'component/button';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import NotificationBubble from 'component/notificationBubble';
|
import NotificationBubble from 'component/notificationBubble';
|
||||||
import Button from 'component/button';
|
import React from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import Tooltip from 'component/common/tooltip';
|
||||||
import { ENABLE_UI_NOTIFICATIONS } from 'config';
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
unseenCount: number,
|
unseenCount: number,
|
||||||
doSeeAllNotifications: () => void,
|
|
||||||
user: ?User,
|
user: ?User,
|
||||||
|
doSeeAllNotifications: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function NotificationHeaderButton(props: Props) {
|
export default function NotificationHeaderButton(props: Props) {
|
||||||
const {
|
const { unseenCount, user, doSeeAllNotifications } = props;
|
||||||
unseenCount,
|
|
||||||
// notifications,
|
|
||||||
// fetching,
|
|
||||||
doSeeAllNotifications,
|
|
||||||
user,
|
|
||||||
} = props;
|
|
||||||
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
|
const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui);
|
||||||
|
|
||||||
function handleMenuClick() {
|
function handleMenuClick() {
|
||||||
if (unseenCount > 0) {
|
if (unseenCount > 0) doSeeAllNotifications();
|
||||||
doSeeAllNotifications();
|
|
||||||
}
|
|
||||||
|
|
||||||
push(`/$/${PAGES.NOTIFICATIONS}`);
|
push(`/$/${PAGES.NOTIFICATIONS}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!notificationsEnabled) {
|
if (!notificationsEnabled) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Tooltip title={__('Notifications')}>
|
||||||
onClick={handleMenuClick}
|
<Button onClick={handleMenuClick} className="header__navigationItem--icon">
|
||||||
aria-label={__('Notifications')}
|
<Icon size={18} icon={ICONS.NOTIFICATION} aria-hidden />
|
||||||
title={__('Notifications')}
|
<NotificationBubble />
|
||||||
className="header__navigation-item menu__title header__navigation-item--icon mobile-hidden"
|
</Button>
|
||||||
>
|
</Tooltip>
|
||||||
<Icon size={18} icon={ICONS.NOTIFICATION} aria-hidden />
|
|
||||||
<NotificationBubble />
|
|
||||||
</Button>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
16
ui/component/headerProfileMenuButton/index.js
Normal file
16
ui/component/headerProfileMenuButton/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { doSignOut } from 'redux/actions/app';
|
||||||
|
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||||
|
import { selectUserEmail } from 'redux/selectors/user';
|
||||||
|
import HeaderProfileMenuButton from './view';
|
||||||
|
|
||||||
|
const select = (state) => ({
|
||||||
|
activeChannelClaim: selectActiveChannelClaim(state),
|
||||||
|
email: selectUserEmail(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
const perform = (dispatch) => ({
|
||||||
|
signOut: () => dispatch(doSignOut()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(select, perform)(HeaderProfileMenuButton);
|
76
ui/component/headerProfileMenuButton/view.jsx
Normal file
76
ui/component/headerProfileMenuButton/view.jsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// @flow
|
||||||
|
import 'scss/component/_header.scss';
|
||||||
|
|
||||||
|
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
|
import * as PAGES from 'constants/pages';
|
||||||
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import HeaderMenuLink from 'component/common/header-menu-link';
|
||||||
|
import Icon from 'component/common/icon';
|
||||||
|
import React from 'react';
|
||||||
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
|
|
||||||
|
type HeaderMenuButtonProps = {
|
||||||
|
activeChannelClaim: ?ChannelClaim,
|
||||||
|
email: ?string,
|
||||||
|
signOut: () => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function HeaderProfileMenuButton(props: HeaderMenuButtonProps) {
|
||||||
|
const { activeChannelClaim, email, signOut } = props;
|
||||||
|
|
||||||
|
const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="header__buttons">
|
||||||
|
<Menu>
|
||||||
|
{activeChannelUrl === undefined ? (
|
||||||
|
<Skeleton variant="circular" animation="wave" className="header__navigationItem--iconSkeleton" />
|
||||||
|
) : (
|
||||||
|
<MenuButton
|
||||||
|
aria-label={__('Your account')}
|
||||||
|
title={__('Your account')}
|
||||||
|
className={classnames('header__navigationItem', {
|
||||||
|
'header__navigationItem--icon': !activeChannelUrl,
|
||||||
|
'header__navigationItem--profilePic': activeChannelUrl,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{activeChannelUrl ? (
|
||||||
|
<ChannelThumbnail uri={activeChannelUrl} small noLazyLoad />
|
||||||
|
) : (
|
||||||
|
<Icon size={18} icon={ICONS.ACCOUNT} aria-hidden />
|
||||||
|
)}
|
||||||
|
</MenuButton>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<MenuList className="menu__list--header">
|
||||||
|
{email ? (
|
||||||
|
<>
|
||||||
|
<HeaderMenuLink page={PAGES.UPLOADS} icon={ICONS.PUBLISH} name={__('Uploads')} />
|
||||||
|
<HeaderMenuLink page={PAGES.CHANNELS} icon={ICONS.CHANNEL} name={__('Channels')} />
|
||||||
|
<HeaderMenuLink page={PAGES.CREATOR_DASHBOARD} icon={ICONS.ANALYTICS} name={__('Creator Analytics')} />
|
||||||
|
<HeaderMenuLink page={PAGES.REWARDS} icon={ICONS.REWARDS} name={__('Rewards')} />
|
||||||
|
<HeaderMenuLink page={PAGES.INVITE} icon={ICONS.INVITE} name={__('Invites')} />
|
||||||
|
|
||||||
|
<MenuItem onSelect={signOut}>
|
||||||
|
<div className="menu__link">
|
||||||
|
<Icon aria-hidden icon={ICONS.SIGN_OUT} />
|
||||||
|
{__('Sign Out')}
|
||||||
|
</div>
|
||||||
|
<span className="menu__link-help">{email}</span>
|
||||||
|
</MenuItem>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<HeaderMenuLink page={PAGES.AUTH_SIGNIN} icon={ICONS.SIGN_IN} name={__('Log In')} />
|
||||||
|
<HeaderMenuLink page={PAGES.AUTH} icon={ICONS.SIGN_UP} name={__('Sign Up')} />
|
||||||
|
<HeaderMenuLink page={PAGES.SETTINGS} icon={ICONS.SETTINGS} name={__('Settings')} />
|
||||||
|
<HeaderMenuLink page={PAGES.HELP} icon={ICONS.HELP} name={__('Help')} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -71,7 +71,7 @@ function LivestreamComment(props: Props) {
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isGlobalMod && (
|
{isGlobalMod && (
|
||||||
<Tooltip label={__('Admin')}>
|
<Tooltip title={__('Admin')}>
|
||||||
<span className="comment__badge comment__badge--global-mod">
|
<span className="comment__badge comment__badge--global-mod">
|
||||||
<Icon icon={ICONS.BADGE_MOD} size={16} />
|
<Icon icon={ICONS.BADGE_MOD} size={16} />
|
||||||
</span>
|
</span>
|
||||||
|
@ -79,7 +79,7 @@ function LivestreamComment(props: Props) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isModerator && (
|
{isModerator && (
|
||||||
<Tooltip label={__('Moderator')}>
|
<Tooltip title={__('Moderator')}>
|
||||||
<span className="comment__badge comment__badge--mod">
|
<span className="comment__badge comment__badge--mod">
|
||||||
<Icon icon={ICONS.BADGE_MOD} size={16} />
|
<Icon icon={ICONS.BADGE_MOD} size={16} />
|
||||||
</span>
|
</span>
|
||||||
|
@ -87,7 +87,7 @@ function LivestreamComment(props: Props) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{commentByOwnerOfContent && (
|
{commentByOwnerOfContent && (
|
||||||
<Tooltip label={__('Streamer')}>
|
<Tooltip title={__('Streamer')}>
|
||||||
<span className="comment__badge">
|
<span className="comment__badge">
|
||||||
<Icon icon={ICONS.BADGE_STREAMER} size={16} />
|
<Icon icon={ICONS.BADGE_STREAMER} size={16} />
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -245,7 +245,7 @@ export default function LivestreamComments(props: Props) {
|
||||||
const isSticker = stickerSuperChats && stickerSuperChats.includes(superChat);
|
const isSticker = stickerSuperChats && stickerSuperChats.includes(superChat);
|
||||||
|
|
||||||
const SuperChatWrapper = !isSticker
|
const SuperChatWrapper = !isSticker
|
||||||
? ({ children }) => <Tooltip label={superChat.comment}>{children}</Tooltip>
|
? ({ children }) => <Tooltip title={superChat.comment}>{children}</Tooltip>
|
||||||
: ({ children }) => <>{children}</>;
|
: ({ children }) => <>{children}</>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,64 +1,27 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
|
||||||
import * as ICONS from 'constants/icons';
|
|
||||||
import { LOGO_TITLE, LOGO, LOGO_TEXT_LIGHT, LOGO_TEXT_DARK } from 'config';
|
|
||||||
import Icon from 'component/common/icon';
|
|
||||||
import { useIsMobile } from 'effects/use-screensize';
|
import { useIsMobile } from 'effects/use-screensize';
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
|
import Icon from 'component/common/icon';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
type: string,
|
|
||||||
currentTheme: string,
|
currentTheme: string,
|
||||||
|
type: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Logo(props: Props) {
|
export default function Logo(props: Props) {
|
||||||
const { type, currentTheme } = props;
|
const { currentTheme, type } = props;
|
||||||
const isMobile = useIsMobile();
|
|
||||||
const defaultWithLabel = (
|
|
||||||
<>
|
|
||||||
<Icon icon={ICONS.LBRY} />
|
|
||||||
{/* @if TARGET='app' */}
|
|
||||||
<div className={'button__label'}>{'LBRY'}</div>
|
|
||||||
{/* @endif */}
|
|
||||||
{/* @if TARGET='web' */}
|
|
||||||
<div className={'button__label'}>{LOGO_TITLE}</div>
|
|
||||||
{/* @endif */}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (type === 'small' || (isMobile && type !== 'embed')) {
|
const isMobile = useIsMobile();
|
||||||
return LOGO ? <img className={'header__navigation-logo'} src={LOGO} /> : <Icon icon={ICONS.LBRY} />;
|
const isLightTheme = currentTheme === 'light';
|
||||||
} else if (type === 'embed') {
|
|
||||||
if (LOGO_TEXT_LIGHT) {
|
if (type === 'embed' || type === 'embed-ended') {
|
||||||
return (
|
return <Icon className="embed__overlay-logo" icon={ICONS.ODYSEE_WHITE_TEXT} />;
|
||||||
<>
|
|
||||||
<img className={'embed__overlay-logo'} src={LOGO_TEXT_LIGHT} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return defaultWithLabel;
|
|
||||||
}
|
|
||||||
} else if (type === 'embed-ended') {
|
|
||||||
if (LOGO_TEXT_LIGHT) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<img className={'embed__overlay-logo'} src={LOGO_TEXT_LIGHT} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return defaultWithLabel;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (LOGO_TEXT_LIGHT && LOGO_TEXT_DARK) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<img
|
|
||||||
className={'header__navigation-logo'}
|
|
||||||
src={currentTheme === 'light' ? LOGO_TEXT_DARK : LOGO_TEXT_LIGHT}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return defaultWithLabel;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'small' || isMobile) {
|
||||||
|
return <Icon className="header__logo" icon={ICONS.ODYSEE_LOGO} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Icon className="header__logo" icon={isLightTheme ? ICONS.ODYSEE_DARK_TEXT : ICONS.ODYSEE_WHITE_TEXT} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import NavigationButton from './view';
|
|
||||||
|
|
||||||
export default NavigationButton;
|
|
|
@ -1,97 +0,0 @@
|
||||||
// @flow
|
|
||||||
import React, { useState, useCallback } from 'react';
|
|
||||||
import * as ICONS from 'constants/icons';
|
|
||||||
import Button from 'component/button';
|
|
||||||
|
|
||||||
// the maximum length of history to show per button
|
|
||||||
const MAX_HISTORY_SIZE = 12;
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
isBackward: boolean,
|
|
||||||
history: {
|
|
||||||
entries: Array<{ key: string, title: string, pathname: string }>,
|
|
||||||
go: number => void,
|
|
||||||
goBack: () => void,
|
|
||||||
goForward: () => void,
|
|
||||||
index: number,
|
|
||||||
length: number,
|
|
||||||
location: { pathname: string },
|
|
||||||
push: string => void,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// determines which slice of entries should make up the back or forward button drop-downs (isBackward vs !isBackward respectively)
|
|
||||||
const sliceEntries = (currentIndex, entries, historyLength, isBackward, maxSize) => {
|
|
||||||
let l = isBackward ? 0 : currentIndex + 1;
|
|
||||||
let r = isBackward ? currentIndex : historyLength;
|
|
||||||
const exceedsMax = maxSize < r - l;
|
|
||||||
if (!exceedsMax) {
|
|
||||||
return entries.slice(l, r);
|
|
||||||
} else if (isBackward) {
|
|
||||||
l = r - maxSize;
|
|
||||||
} else {
|
|
||||||
r = l + maxSize;
|
|
||||||
}
|
|
||||||
return entries.slice(l, r);
|
|
||||||
};
|
|
||||||
|
|
||||||
const NavigationButton = (props: Props) => {
|
|
||||||
const { isBackward, history } = props;
|
|
||||||
const { entries, go } = history;
|
|
||||||
const currentIndex = history.index;
|
|
||||||
const historyLength = history.length;
|
|
||||||
const [showHistory, setShowHistory] = useState(false);
|
|
||||||
|
|
||||||
// creates an <li> intended for the button's <ul>
|
|
||||||
const makeItem = useCallback(
|
|
||||||
(entry: { pathname: string, title: string, key: string }, index: number) => {
|
|
||||||
// difference between the current index and the index of the entry
|
|
||||||
const backwardDif = index - (currentIndex < MAX_HISTORY_SIZE ? currentIndex : MAX_HISTORY_SIZE);
|
|
||||||
const forwardDif = index + 1;
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
className="header__navigation-button"
|
|
||||||
role="link"
|
|
||||||
key={entry.key}
|
|
||||||
onMouseDown={() => {
|
|
||||||
setShowHistory(false);
|
|
||||||
go(isBackward ? backwardDif : forwardDif);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>{entry.title}</span>
|
|
||||||
<span className="header__navigation-button-help">{entry.pathname === '/' ? __('Home') : entry.pathname}</span>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[currentIndex, isBackward, go]
|
|
||||||
);
|
|
||||||
const slicedEntries = sliceEntries(currentIndex, entries, historyLength, isBackward, MAX_HISTORY_SIZE);
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
// @if TARGET='app'
|
|
||||||
onDoubleClick={e => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
// @endif
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
className={`header__navigation-item header__navigation-item--${isBackward ? 'back' : 'forward'}`}
|
|
||||||
description={isBackward ? __('Navigate back') : __('Navigate forward')}
|
|
||||||
onBlur={() => setShowHistory(false)}
|
|
||||||
onClick={() => (isBackward ? history.goBack() : history.goForward())}
|
|
||||||
onContextMenu={e => {
|
|
||||||
setShowHistory(!showHistory);
|
|
||||||
// the following three lines prevent the regular context menu (right click menu) from appearing
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
return false;
|
|
||||||
}}
|
|
||||||
icon={isBackward ? ICONS.ARROW_LEFT : ICONS.ARROW_RIGHT}
|
|
||||||
iconSize={18}
|
|
||||||
disabled={slicedEntries.length === 0}
|
|
||||||
/>
|
|
||||||
{showHistory && <ul className={'header__navigation-dropdown'}>{slicedEntries.map(makeItem)}</ul>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default NavigationButton;
|
|
|
@ -2,7 +2,7 @@
|
||||||
// https://github.com/carmelopullara/react-feather
|
// https://github.com/carmelopullara/react-feather
|
||||||
// Note: Icons should be named for their purpose, rather than the actual icon.
|
// Note: Icons should be named for their purpose, rather than the actual icon.
|
||||||
// The goal being to reduce multiple uses of the same icon for different purposes.
|
// The goal being to reduce multiple uses of the same icon for different purposes.
|
||||||
//
|
|
||||||
export const REWARDS = 'Award';
|
export const REWARDS = 'Award';
|
||||||
export const LOCAL = 'Folder';
|
export const LOCAL = 'Folder';
|
||||||
export const ALERT = 'AlertCircle';
|
export const ALERT = 'AlertCircle';
|
||||||
|
@ -183,3 +183,6 @@ export const EMOJI = 'Emoji';
|
||||||
export const STICKER = 'Sticker';
|
export const STICKER = 'Sticker';
|
||||||
export const EDUCATION = 'Education';
|
export const EDUCATION = 'Education';
|
||||||
export const POP_CULTURE = 'Pop Culture';
|
export const POP_CULTURE = 'Pop Culture';
|
||||||
|
export const ODYSEE_LOGO = 'OdyseeLogo';
|
||||||
|
export const ODYSEE_WHITE_TEXT = 'OdyseeLogoWhiteText';
|
||||||
|
export const ODYSEE_DARK_TEXT = 'OdyseeLogoDarkText';
|
||||||
|
|
|
@ -35,7 +35,6 @@ export const WALLET_PASSWORD_UNSAVE = 'wallet_password_unsave';
|
||||||
export const CREATE_CHANNEL = 'create_channel';
|
export const CREATE_CHANNEL = 'create_channel';
|
||||||
export const YOUTUBE_WELCOME = 'youtube_welcome';
|
export const YOUTUBE_WELCOME = 'youtube_welcome';
|
||||||
export const SET_REFERRER = 'set_referrer';
|
export const SET_REFERRER = 'set_referrer';
|
||||||
export const SIGN_OUT = 'sign_out';
|
|
||||||
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
export const LIQUIDATE_SUPPORTS = 'liquidate_supports';
|
||||||
export const MASS_TIP_UNLOCK = 'mass_tip_unlock';
|
export const MASS_TIP_UNLOCK = 'mass_tip_unlock';
|
||||||
export const CONFIRM_AGE = 'confirm_age';
|
export const CONFIRM_AGE = 'confirm_age';
|
||||||
|
|
|
@ -73,7 +73,6 @@ const ModalRevokeClaim = lazyImport(() => import('modal/modalRevokeClaim' /* web
|
||||||
const ModalRewardCode = lazyImport(() => import('modal/modalRewardCode' /* webpackChunkName: "modalRewardCode" */));
|
const ModalRewardCode = lazyImport(() => import('modal/modalRewardCode' /* webpackChunkName: "modalRewardCode" */));
|
||||||
const ModalSendTip = lazyImport(() => import('modal/modalSendTip' /* webpackChunkName: "modalSendTip" */));
|
const ModalSendTip = lazyImport(() => import('modal/modalSendTip' /* webpackChunkName: "modalSendTip" */));
|
||||||
const ModalSetReferrer = lazyImport(() => import('modal/modalSetReferrer' /* webpackChunkName: "modalSetReferrer" */));
|
const ModalSetReferrer = lazyImport(() => import('modal/modalSetReferrer' /* webpackChunkName: "modalSetReferrer" */));
|
||||||
const ModalSignOut = lazyImport(() => import('modal/modalSignOut' /* webpackChunkName: "modalSignOut" */));
|
|
||||||
const ModalSocialShare = lazyImport(() => import('modal/modalSocialShare' /* webpackChunkName: "modalSocialShare" */));
|
const ModalSocialShare = lazyImport(() => import('modal/modalSocialShare' /* webpackChunkName: "modalSocialShare" */));
|
||||||
const ModalSupportsLiquidate = lazyImport(() =>
|
const ModalSupportsLiquidate = lazyImport(() =>
|
||||||
import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */)
|
import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */)
|
||||||
|
@ -157,8 +156,6 @@ function getModal(id) {
|
||||||
return ModalYoutubeWelcome;
|
return ModalYoutubeWelcome;
|
||||||
case MODALS.SET_REFERRER:
|
case MODALS.SET_REFERRER:
|
||||||
return ModalSetReferrer;
|
return ModalSetReferrer;
|
||||||
case MODALS.SIGN_OUT:
|
|
||||||
return ModalSignOut;
|
|
||||||
case MODALS.CONFIRM_AGE:
|
case MODALS.CONFIRM_AGE:
|
||||||
return ModalConfirmAge;
|
return ModalConfirmAge;
|
||||||
case MODALS.FILE_SELECTION:
|
case MODALS.FILE_SELECTION:
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { doSignOut, doHideModal } from 'redux/actions/app';
|
|
||||||
import ModalSignOut from './view';
|
|
||||||
|
|
||||||
export default connect(null, {
|
|
||||||
doSignOut,
|
|
||||||
doHideModal,
|
|
||||||
})(ModalSignOut);
|
|
|
@ -1,47 +0,0 @@
|
||||||
// @flow
|
|
||||||
import React from 'react';
|
|
||||||
import { Modal } from 'modal/modal';
|
|
||||||
import Card from 'component/common/card';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import I18nMessage from 'component/i18nMessage';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
doHideModal: () => void,
|
|
||||||
doSignOut: () => void,
|
|
||||||
};
|
|
||||||
|
|
||||||
function ModalRepost(props: Props) {
|
|
||||||
const { doHideModal, doSignOut } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal isOpen type="card">
|
|
||||||
<Card
|
|
||||||
title={__('Sign out')}
|
|
||||||
subtitle={
|
|
||||||
<I18nMessage
|
|
||||||
tokens={{
|
|
||||||
rename_wallet_instructions: (
|
|
||||||
<Button
|
|
||||||
button="link"
|
|
||||||
label={__('rename your existing wallet')}
|
|
||||||
href="https://lbry.com/faq/lbry-directories"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Your wallet data will remain intact. If you sign in with a different account, the wallets will be merged. To
|
|
||||||
prevent this, you need to %rename_wallet_instructions% in the lbry/wallets directory.
|
|
||||||
</I18nMessage>
|
|
||||||
}
|
|
||||||
actions={
|
|
||||||
<div className="section__actions">
|
|
||||||
<Button button="primary" label={__('Sign Out')} onClick={doSignOut} />
|
|
||||||
<Button button="link" label={__('Cancel')} onClick={doHideModal} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ModalRepost;
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { selectClaimWithId, selectMyChannelClaims, selectStakedLevelForChannelUri } from 'redux/selectors/claims';
|
import { selectClaimWithId, selectMyChannelClaims, selectStakedLevelForChannelUri } from 'redux/selectors/claims';
|
||||||
|
import { selectUserEmail } from 'redux/selectors/user';
|
||||||
|
|
||||||
export const selectState = (state) => state.app || {};
|
export const selectState = (state) => state.app || {};
|
||||||
|
|
||||||
|
@ -66,15 +67,17 @@ export const selectActiveChannelId = (state) => selectState(state).activeChannel
|
||||||
|
|
||||||
export const selectActiveChannelClaim = createSelector(
|
export const selectActiveChannelClaim = createSelector(
|
||||||
(state) => selectClaimWithId(state, selectActiveChannelId(state)), // i.e. 'byId[activeChannelId]' specifically, instead of just 'byId'.
|
(state) => selectClaimWithId(state, selectActiveChannelId(state)), // i.e. 'byId[activeChannelId]' specifically, instead of just 'byId'.
|
||||||
|
(state) => selectUserEmail(state),
|
||||||
selectMyChannelClaims,
|
selectMyChannelClaims,
|
||||||
(activeChannelClaim, myChannelClaims) => {
|
(activeChannelClaim, userEmail, myChannelClaims) => {
|
||||||
if (!activeChannelClaim || !myChannelClaims || !myChannelClaims.length) {
|
// Null: has none. Undefined: not resolved, default state, could have or not
|
||||||
|
if (!userEmail || myChannelClaims === null) {
|
||||||
|
return null;
|
||||||
|
} else if (!activeChannelClaim || !myChannelClaims || !myChannelClaims.length) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeChannelClaim) {
|
if (activeChannelClaim) return activeChannelClaim;
|
||||||
return activeChannelClaim;
|
|
||||||
}
|
|
||||||
|
|
||||||
const myChannelClaimsByEffectiveAmount = myChannelClaims.slice().sort((a, b) => {
|
const myChannelClaimsByEffectiveAmount = myChannelClaims.slice().sort((a, b) => {
|
||||||
const effectiveAmountA = (a.meta && Number(a.meta.effective_amount)) || 0;
|
const effectiveAmountA = (a.meta && Number(a.meta.effective_amount)) || 0;
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
@import 'component/file-render';
|
@import 'component/file-render';
|
||||||
@import 'component/footer';
|
@import 'component/footer';
|
||||||
@import 'component/form-field';
|
@import 'component/form-field';
|
||||||
@import 'component/header';
|
|
||||||
@import 'component/icon';
|
@import 'component/icon';
|
||||||
@import 'component/main';
|
@import 'component/main';
|
||||||
@import 'component/markdown-editor';
|
@import 'component/markdown-editor';
|
||||||
|
|
|
@ -366,17 +366,6 @@ $actions-z-index: 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.channel-staked__tooltip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
line-height: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-staked__tooltip-text {
|
|
||||||
margin-left: var(--spacing-xs);
|
|
||||||
font-size: var(--font-xsmall);
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-staked__wrapper {
|
.channel-staked__wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
@import '../init/breakpoints';
|
||||||
|
@import '../init/mixins';
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
z-index: 3; // Main content uses z-index: 1, other content uses z-index: 2, this ensures it always scrolls under the header
|
z-index: 3; // Main content uses z-index: 1, other content uses z-index: 2, this ensures it always scrolls under the header
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -6,6 +9,7 @@
|
||||||
background-color: var(--color-header-background);
|
background-color: var(--color-header-background);
|
||||||
box-shadow: var(--card-box-shadow);
|
box-shadow: var(--card-box-shadow);
|
||||||
font-size: var(--font-body);
|
font-size: var(--font-body);
|
||||||
|
user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
|
@ -23,62 +27,92 @@
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
width: inherit;
|
width: unset;
|
||||||
height: inherit;
|
height: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > * {
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header--minimal {
|
.header--minimal {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
|
||||||
|
|
||||||
.header--mac {
|
.header__navigation {
|
||||||
padding-top: var(--mac-titlebar-height);
|
padding: var(--spacing-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header__navigationItem--logo {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__contents {
|
.header__contents {
|
||||||
height: calc(var(--header-height));
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 var(--spacing-m);
|
flex: 1;
|
||||||
|
height: var(--header-height);
|
||||||
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
padding: var(--spacing-xs);
|
padding: var(--spacing-xs);
|
||||||
|
height: var(--header-height-mobile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation {
|
.header__navigation {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
height: var(--header-height);
|
||||||
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
padding: var(--spacing-xs);
|
||||||
|
height: var(--header-height-mobile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header__menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__menu {
|
.header__menu--left {
|
||||||
margin-left: auto;
|
@extend .header__menu;
|
||||||
display: flex;
|
justify-content: flex-start;
|
||||||
justify-content: space-between;
|
}
|
||||||
align-items: center;
|
|
||||||
|
.header__menu--right {
|
||||||
|
@extend .header__menu;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 10rem;
|
||||||
|
min-width: 10rem;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
width: unset;
|
||||||
|
min-width: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__buttons {
|
.header__buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-logo {
|
.header__logo {
|
||||||
height: var(--height-button);
|
height: var(--height-button);
|
||||||
max-width: -webkit-fit-content;
|
max-width: -webkit-fit-content;
|
||||||
max-width: -moz-fit-content;
|
max-width: -moz-fit-content;
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
height: var(--height-button-mobile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item {
|
.header__navigationItem {
|
||||||
height: var(--height-button);
|
height: var(--height-button);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -90,11 +124,18 @@
|
||||||
svg {
|
svg {
|
||||||
stroke: var(--color-text);
|
stroke: var(--color-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[aria-expanded='true'] {
|
||||||
|
background-color: var(--color-header-button-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
height: var(--height-button-mobile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item--back,
|
.header__navigationItem--icon {
|
||||||
.header__navigation-item--forward,
|
@extend .header__navigationItem;
|
||||||
.header__navigation-item--icon {
|
|
||||||
width: var(--height-button);
|
width: var(--height-button);
|
||||||
background-color: var(--color-header-button);
|
background-color: var(--color-header-button);
|
||||||
border-radius: 1.5rem;
|
border-radius: 1.5rem;
|
||||||
|
@ -110,6 +151,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
margin: 0;
|
||||||
|
width: var(--height-button-mobile);
|
||||||
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -117,8 +163,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item--profile-pic {
|
.header__navigationItem--profilePic {
|
||||||
margin-left: var(--spacing-m);
|
margin-right: var(--spacing-s);
|
||||||
|
background-color: var(--color-header-button);
|
||||||
|
|
||||||
.channel-thumbnail {
|
.channel-thumbnail {
|
||||||
height: var(--height-button);
|
height: var(--height-button);
|
||||||
|
@ -129,43 +176,68 @@
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.channel-thumbnail {
|
||||||
|
height: var(--height-button-mobile);
|
||||||
|
width: var(--height-button-mobile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item--balance {
|
.header__navigationItem--iconSkeleton {
|
||||||
@extend .button--file-action;
|
@extend .header__navigationItem--icon;
|
||||||
|
height: var(--height-button) !important;
|
||||||
|
width: var(--height-button) !important;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
height: var(--height-button-mobile) !important;
|
||||||
|
width: var(--height-button-mobile) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header__navigationItem--balance {
|
||||||
|
@extend .header__navigationItem;
|
||||||
margin: 0 var(--spacing-s);
|
margin: 0 var(--spacing-s);
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-item--forward {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-item--icon {
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
margin: 0;
|
margin: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
width: 5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__navigation-item--lbry {
|
.header__navigationItem--balanceLoading {
|
||||||
height: 4rem;
|
margin: 0 var(--spacing-s);
|
||||||
|
width: 4rem;
|
||||||
|
background-color: var(--color-header-button);
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header__navigationItem--logo {
|
||||||
|
@extend .header__navigationItem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: var(--spacing-m);
|
margin: 0 var(--spacing-s);
|
||||||
margin-right: var(--spacing-m);
|
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
// move to lbry theme?
|
|
||||||
.lbry-icon {
|
@media (min-width: $breakpoint-small) {
|
||||||
height: var(--height-button);
|
width: 150px;
|
||||||
width: var(--height-button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
margin-right: var(--spacing-m);
|
margin-right: var(--spacing-m);
|
||||||
height: 5rem;
|
|
||||||
|
|
||||||
.button__label {
|
.button__label {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -173,61 +245,43 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header--minimal {
|
.header__authButtons {
|
||||||
.header__navigation-item--lbry {
|
|
||||||
height: 3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-dropdown {
|
|
||||||
@extend .menu__list--header;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
list-style-type: none;
|
|
||||||
background-color: var(--color-header-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-button {
|
|
||||||
margin: 0;
|
|
||||||
padding: var(--spacing-xxs) var(--spacing-m);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: var(--color-menu-background--active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__navigation-button-help {
|
|
||||||
@extend .help;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-left: var(--spacing-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header__auth-buttons {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
margin-left: var(--spacing-s);
|
|
||||||
|
|
||||||
& > *:not(:last-child) {
|
& > *:not(:last-child) {
|
||||||
margin: 0 var(--spacing-m);
|
margin: 0 var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
.button--link {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button--primary {
|
||||||
|
padding: var(--spacing-xxs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__center {
|
.header__center {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@media (min-width: $breakpoint-small) {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__auth-title {
|
.header__authTitle {
|
||||||
|
@extend .header__center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
@media (min-width: $breakpoint-small) {
|
@media (min-width: $breakpoint-small) {
|
||||||
font-size: var(--font-large);
|
font-size: var(--font-large);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ReactModal__Overlay {
|
||||||
|
.button--close {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
padding: var(--spacing-xs);
|
padding: var(--spacing-xs);
|
||||||
padding-top: var(--spacing-m);
|
margin-top: var(--header-height-mobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: $breakpoint-large) {
|
@media (min-width: $breakpoint-large) {
|
||||||
|
@ -86,6 +86,7 @@
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: calc(100vh - var(--header-height-mobile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
.navigation__wrapper {
|
.navigation__wrapper {
|
||||||
width: var(--side-nav-width);
|
width: var(--side-nav-width);
|
||||||
height: calc(100vh - var(--header-height));
|
height: calc(100vh - var(--header-height));
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
height: calc(100vh - var(--header-height-mobile));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation__wrapper--micro {
|
.navigation__wrapper--micro {
|
||||||
|
@ -48,6 +52,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
top: var(--header-height-mobile);
|
||||||
|
height: calc(100vh - var(--header-height-mobile));
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding-bottom: var(--spacing-s);
|
padding-bottom: var(--spacing-s);
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
@ -294,6 +303,10 @@
|
||||||
&.navigation__overlay--mac {
|
&.navigation__overlay--mac {
|
||||||
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
top: var(--header-height-mobile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation__overlay--active {
|
.navigation__overlay--active {
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
[data-reach-tooltip] {
|
.MuiTooltip-tooltip {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius) !important;
|
||||||
background-color: var(--color-tooltip-bg);
|
background-color: var(--color-tooltip-bg) !important;
|
||||||
color: var(--color-tooltip-text);
|
color: var(--color-tooltip-text) !important;
|
||||||
border: none;
|
font-size: var(--font-small) !important;
|
||||||
padding: var(--spacing-s);
|
}
|
||||||
overflow: hidden;
|
|
||||||
|
.MuiTooltip-arrow {
|
||||||
|
color: var(--color-tooltip-bg) !important;
|
||||||
|
font-size: var(--font-xxsmall) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-staked__tooltip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1rem;
|
||||||
|
padding: var(--spacing-xs);
|
||||||
|
|
||||||
|
.channel-staked__tooltip-text {
|
||||||
|
margin-left: var(--spacing-xs);
|
||||||
|
font-size: var(--font-xsmall);
|
||||||
|
font-size: var(--font-small);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import './header';
|
||||||
|
|
||||||
.wunderbar__wrapper {
|
.wunderbar__wrapper {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
max-width: 30rem;
|
max-width: 30rem;
|
||||||
|
@ -8,7 +10,7 @@
|
||||||
.wunderbar__wrapper--mobile {
|
.wunderbar__wrapper--mobile {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
height: var(--header-height);
|
height: var(--header-height-mobile);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -103,7 +105,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: calc(var(--header-height) - (var(--height-input)) + 3px);
|
top: calc(var(--header-height) - var(--spacing-m) - 3px);
|
||||||
@extend .card;
|
@extend .card;
|
||||||
box-shadow: var(--card-box-shadow);
|
box-shadow: var(--card-box-shadow);
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
|
@ -111,10 +113,14 @@
|
||||||
border-top: none;
|
border-top: none;
|
||||||
padding-top: var(--spacing-xs);
|
padding-top: var(--spacing-xs);
|
||||||
margin: 0 var(--spacing-s);
|
margin: 0 var(--spacing-s);
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
top: calc(var(--header-height-mobile) - (var(--height-input)) + 3px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wunderbar__suggestions--mobile {
|
.wunderbar__suggestions--mobile {
|
||||||
top: calc(var(--header-height) - var(--spacing-xs));
|
top: calc(var(--header-height-mobile) - var(--spacing-xs));
|
||||||
margin-top: var(--spacing-m);
|
margin-top: var(--spacing-m);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
@ -227,7 +233,7 @@
|
||||||
|
|
||||||
.wunderbar__mobile-search {
|
.wunderbar__mobile-search {
|
||||||
@extend .button--alt;
|
@extend .button--alt;
|
||||||
@extend .header__navigation-item--icon;
|
@extend .header__navigationItem--icon;
|
||||||
padding: var(--spacing-xs);
|
padding: var(--spacing-xs);
|
||||||
margin-right: var(--spacing-m);
|
margin-right: var(--spacing-m);
|
||||||
|
|
||||||
|
|
|
@ -65,12 +65,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__title {
|
|
||||||
&[aria-expanded='true'] {
|
|
||||||
background-color: var(--color-header-button-active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu__list {
|
.menu__list {
|
||||||
box-shadow: var(--card-box-shadow);
|
box-shadow: var(--card-box-shadow);
|
||||||
animation: menu-animate-in var(--animation-duration) var(--animation-style);
|
animation: menu-animate-in var(--animation-duration) var(--animation-style);
|
||||||
|
@ -86,7 +80,7 @@
|
||||||
|
|
||||||
.menu__list--header {
|
.menu__list--header {
|
||||||
@extend .menu__list;
|
@extend .menu__list;
|
||||||
margin-top: 19px;
|
margin-top: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__list--comments {
|
.menu__list--comments {
|
||||||
|
|
|
@ -479,12 +479,6 @@ textarea {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-hidden {
|
|
||||||
@media (max-width: $breakpoint-small) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ads-test {
|
.ads-test {
|
||||||
height: 50vh;
|
height: 50vh;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
--border-radius: 10px;
|
--border-radius: 10px;
|
||||||
--height-input: 2.5rem;
|
--height-input: 2.5rem;
|
||||||
--height-button: 2.5rem;
|
--height-button: 2.5rem;
|
||||||
|
--height-button-mobile: 2rem;
|
||||||
--height-checkbox: 24px;
|
--height-checkbox: 24px;
|
||||||
--height-radio: 24px;
|
--height-radio: 24px;
|
||||||
--height-badge: 24px;
|
--height-badge: 24px;
|
||||||
|
@ -66,7 +67,8 @@
|
||||||
// Header
|
// Header
|
||||||
// This is tied to the floating player so it knows where to attach to
|
// This is tied to the floating player so it knows where to attach to
|
||||||
// ui/component/fileRenderFloating/view.jsx
|
// ui/component/fileRenderFloating/view.jsx
|
||||||
--header-height: 80px;
|
--header-height: 64px;
|
||||||
|
--header-height-mobile: 56px;
|
||||||
|
|
||||||
// Inline Player
|
// Inline Player
|
||||||
--inline-player-max-height: calc(100vh - var(--header-height) - var(--spacing-l) * 4);
|
--inline-player-max-height: calc(100vh - var(--header-height) - var(--spacing-l) * 4);
|
||||||
|
|
|
@ -104,6 +104,7 @@
|
||||||
--color-purchased-text: black;
|
--color-purchased-text: black;
|
||||||
--color-thumbnail-background: var(--color-gray-5);
|
--color-thumbnail-background: var(--color-gray-5);
|
||||||
--color-tooltip-bg: #2f3337;
|
--color-tooltip-bg: #2f3337;
|
||||||
|
--color-tooltip-text: #fafafa;
|
||||||
--color-focus: #e91e6329;
|
--color-focus: #e91e6329;
|
||||||
--color-placeholder-background: #261a35;
|
--color-placeholder-background: #261a35;
|
||||||
--color-spinner-light: white;
|
--color-spinner-light: white;
|
||||||
|
|
Loading…
Reference in a new issue