UserMenu basic implementation

This commit is contained in:
NikolaBorislavovHristov 2019-05-08 19:36:25 +03:00
parent d39c14b554
commit 0255b93258
5 changed files with 210 additions and 165 deletions

View file

@ -1,22 +1,109 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const Icon = require('stremio-icons/dom');
const Popup = require('../../Popup');
const { Input } = require('stremio-navigation');
const styles = require('./styles');
const UserMenu = ({ className }) => (
<Popup>
<Popup.Label>
<Input className={classnames(className, styles['user-menu-button'])} type={'button'}>
<Icon className={classnames(styles['icon'], styles['user-icon'])} icon={'ic_user'} />
<Icon className={classnames(styles['icon'], styles['arrow-icon'])} icon={'ic_arrow_down'} />
</Input>
</Popup.Label>
<Popup.Menu>
<div style={{ background: 'red', width: 400, height: 300 }}>userpanel</div>
</Popup.Menu>
</Popup>
);
const UserMenu = ({ className, email, avatar, logout }) => {
const [fullscreen, setFullscreen] = React.useState(document.fullscreenElement instanceof HTMLElement);
const toggleFullscreen = React.useCallback(() => {
if (fullscreen) {
document.exitFullscreen();
} else {
document.documentElement.requestFullscreen();
}
}, [fullscreen]);
const onFullscreenChange = React.useCallback(() => {
setFullscreen(document.fullscreenElement instanceof HTMLElement);
}, []);
React.useEffect(() => {
document.addEventListener('fullscreenchange', onFullscreenChange);
return () => {
document.removeEventListener('fullscreenchange', onFullscreenChange);
};
}, []);
return (
<Popup modalContainerClassName={styles['user-menu-modal-container']}>
<Popup.Label>
<Input className={classnames(className, styles['user-menu-button'])} tabIndex={-1} type={'button'}>
<Icon className={classnames(styles['icon'], styles['user-icon'])} icon={'ic_user'} />
<Icon className={classnames(styles['icon'], styles['arrow-icon'])} icon={'ic_arrow_down'} />
</Input>
</Popup.Label>
<Popup.Menu>
<div className={styles['user-menu']}>
<div className={styles['user-info']}>
<div
className={styles['avatar']}
style={{
backgroundImage: email.length === 0 ?
`url('/images/anonymous.png')`
:
`url('${avatar}'), url('/images/default_avatar.png')`
}}
/>
<div className={styles['email-container']}>
<div className={styles['user-info-label']}>{email.length === 0 ? 'Anonymous user' : email}</div>
</div>
<Input className={styles['login-logout-button']} tabIndex={-1} type={email.length === 0 ? 'link' : 'button'} href={email.length === 0 ? '#/intro' : null} onClick={email.length === 0 ? null : logout}>
<div className={styles['user-info-label']}>{email.length === 0 ? 'Log in / Sign up' : 'Log out'}</div>
</Input>
</div>
<div className={styles['user-menu-section']}>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'button'} onClick={toggleFullscreen}>
<Icon className={styles['option-icon']} icon={'ic_fullscreen'} />
<div className={styles['option-label']}>{fullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen'}</div>
</Input>
</div>
<div className={styles['user-menu-section']}>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'link'} href={'#/settings'}>
<Icon className={styles['option-icon']} icon={'ic_settings'} />
<div className={styles['option-label']}>Settings</div>
</Input>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'link'} href={'#/addons'}>
<Icon className={styles['option-icon']} icon={'ic_addons'} />
<div className={styles['option-label']}>Addons</div>
</Input>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'button'}>
<Icon className={styles['option-icon']} icon={'ic_remote'} />
<div className={styles['option-label']}>Remote Control</div>
</Input>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'button'}>
<Icon className={styles['option-icon']} icon={'ic_magnet'} />
<div className={styles['option-label']}>Play Magnet Link</div>
</Input>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'link'} href={'https://stremio.zendesk.com/'} target={'_blank'}>
<Icon className={styles['option-icon']} icon={'ic_help'} />
<div className={styles['option-label']}>Help & Feedback</div>
</Input>
</div>
<div className={styles['user-menu-section']}>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'link'} href={'https://www.stremio.com/tos'} target={'_blank'}>
<div className={styles['option-label']}>Terms of Service</div>
</Input>
<Input className={classnames(styles['option'], 'focusable-with-border')} type={'link'} href={'https://www.stremio.com/'} target={'_blank'}>
<div className={styles['option-label']}>About Stremio</div>
</Input>
</div>
</div>
</Popup.Menu>
</Popup>
);
};
UserMenu.propTypes = {
className: PropTypes.string,
email: PropTypes.string.isRequired,
avatar: PropTypes.string.isRequired,
logout: PropTypes.func.isRequired
};
UserMenu.defaultProps = {
email: '',
avatar: ''
};
module.exports = UserMenu;

View file

@ -1,3 +1,8 @@
.user-menu {
--user-menu-width: 280px;
font-size: 14px;
}
.user-menu-button {
text-align: center;
overflow: hidden;
@ -19,4 +24,109 @@
width: 16%;
}
}
}
.user-menu-modal-container {
--box-shadow: -0.6em .6em .5em -0.1em var(--color-backgrounddark40);
.user-menu {
width: var(--user-menu-width);
background-color: var(--color-background);
.user-info {
display: grid;
width: 100%;
height: 6em;
grid-template-columns: 6em 1fr;
grid-template-rows: 50% 50%;
grid-template-areas:
"avatar email"
"avatar login-logout-button";
.avatar {
grid-area: avatar;
padding: 0.8em;
border-radius: 50%;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-origin: content-box;
background-clip: content-box;
}
.email-container {
grid-area: email;
display: flex;
flex-direction: row;
align-items: center;
padding: 0.8em 0.8em 0 0;
color: var(--color-surfacelighter);
overflow: hidden;
}
.login-logout-button {
grid-area: login-logout-button;
display: flex;
flex-direction: row;
align-items: center;
padding: 0 0.8em 0.8em 0;
color: var(--color-surface);
overflow: hidden;
cursor: pointer;
&:hover {
color: var(--color-surfacelighter);
}
}
.email-container, .login-logout-button {
.user-info-label {
flex: 1;
max-height: 100%;
line-height: 1.1em;
word-break: break-all;
overflow: hidden;
}
}
}
.user-menu-section {
width: 100%;
border-top: calc(0.5 * var(--focusable-border-size)) solid var(--color-surfacedark80);
.option {
width: 100%;
height: 4em;
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
&:hover {
background-color: var(--color-backgroundlighter);
}
.option-icon {
width: 4em;
height: 4em;
padding: 1.3em;
fill: var(--color-secondarylight);
}
.option-label {
flex: 1;
padding-right: 1.3em;
max-height: 2.2em;
line-height: 1.1em;
color: var(--color-surfacelighter);
word-break: break-all;
overflow: hidden;
&:only-child {
padding-left: 1.3em;
}
}
}
}
}
}

View file

@ -1,69 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'stremio-icons/dom';
import styles from './styles';
const renderAvatar = (avatar, email) => {
if (email.length === 0) {
return (
<div style={{ backgroundImage: `url('/images/anonymous.png')` }} className={styles['avatar']} />
);
}
return (
<div style={{ backgroundImage: `url('${avatar}'), url('/images/default_avatar.png') ` }} className={styles['avatar']} />
);
}
const renderEmail = (email) => {
return (
<div className={styles['email']}>{email.length === 0 ? 'Anonymous' : email}</div>
);
}
const UserPanel = (props) => {
return (
<div className={styles['user-panel']}>
<div className={styles['user-info']}>
{renderAvatar(props.avatar, props.email)}
{renderEmail(props.email)}
<div onClick={props.email.length === 0 ? props.login : props.logout} className={styles['login-logout']}>{props.email.length === 0 ? 'Log in' : 'Log out'}</div>
</div>
<div className={styles['separator']}></div>
<div onClick={props.resizeWindow} className={styles['option']}>
<Icon className={styles['icon']} icon={'ic_fullscreen'} />Fullscreen mode
</div>
<div className={styles['separator']}></div>
<a href={'#settings'} className={styles['option']}>
<Icon className={styles['icon']} icon={'ic_settings'} />Settings
</a>
<a href={'#addons'} className={styles['option']}>
<Icon className={styles['icon']} icon={'ic_addons'} />Add-ons
</a>
<div onClick={props.playMagnetLink} className={styles['option']}>
<Icon className={styles['icon']} icon={'ic_magnet'} />Play Magnet Link
</div>
<a href={'https://stremio.zendesk.com'} target={'_blank'} className={styles['option']}>
<Icon className={styles['icon']} icon={'ic_help'} />Help & Feedback
</a>
<div className={styles['separator']}></div>
<a href={'https://www.stremio.com/tos'} target={'_blank'} className={styles['option']}>Terms of Service</a>
<a href={'https://www.stremio.com'} target={'_blank'} className={styles['option']}>About Stremio</a>
</div>
);
}
UserPanel.propTypes = {
avatar: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
login: PropTypes.func,
logout: PropTypes.func,
resizeWindow: PropTypes.func,
playMagnetLink: PropTypes.func,
};
UserPanel.defaultProps = {
avatar: '',
email: ''
};
export default UserPanel;

View file

@ -1,3 +0,0 @@
import UserPanel from './UserPanel';
export default UserPanel;

View file

@ -1,80 +0,0 @@
.user-panel {
--user-panel-width: 260px;
--spacing: 16px;
--separator-height: 1px;
}
.user-panel {
width: var(--user-panel-width);
background-color: var(--color-backgroundlighter);
.user-info {
display: grid;
padding: var(--spacing);
grid-template-columns: calc(0.2 * var(--user-panel-width)) auto;
grid-template-rows: calc(0.1 * var(--user-panel-width)) calc(0.1 * var(--user-panel-width));
grid-template-areas:
"avatar email"
"avatar login-logout";
.avatar {
grid-area: avatar;
border-radius: 50%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.email {
grid-area: email;
display: flex;
align-items: center;
color: var(--color-surfacelighter);
padding-left: var(--spacing);
overflow: hidden;
white-space: pre;
text-overflow: ellipsis;
}
.login-logout {
grid-area: login-logout;
display: flex;
align-items: center;
color: var(--color-surface);
padding-left: var(--spacing);
overflow: hidden;
white-space: pre;
text-overflow: ellipsis;
&:hover {
cursor: pointer;
color: var(--color-surfacelighter);
}
}
}
.option {
display: flex;
align-items: center;
padding: var(--spacing);
color: var(--color-surfacelighter80);
.icon {
width: calc(var(--user-panel-width) * 0.08);
height: calc(var(--user-panel-width) * 0.08);
margin-right: var(--spacing);
fill: var(--color-secondarylighter);
}
&:hover {
cursor: pointer;
color: var(--color-surfacelighter);
background-color: var(--color-secondarylighter20);
}
}
.separator {
height: var(--separator-height);
background-color: var(--color-surface);
}
}