import React from 'react' import dynamic from 'next/dynamic' import { withRouter } from 'next/router' import Dropdown from '../Dropdown' import { managePopout } from '../Popout' import ThemeIcon from '../svg/Theme' import RemoveIcon from '../svg/Remove' import { THEMES, COLORS, DEFAULT_THEME, HIGHLIGHT_KEYS } from '../../lib/constants' import { getThemes, saveThemes, stringifyRGBA, generateId } from '../../lib/util' import { getRouteState } from '../../lib/routing' const ThemeCreate = dynamic(() => import('./ThemeCreate'), { loading: () => null }) const ThemeItem = ({ children, item, isSelected, onClick }) => (
{children} {item.custom && !isSelected && (
)}
) const themeIcon = const getCustomName = themes => `Custom Theme ${themes.filter(({ name }) => name.startsWith('Custom Theme')).length + 1}` class Themes extends React.PureComponent { selectedTheme = DEFAULT_THEME state = { themes: THEMES, preset: this.props.theme, name: 'Custom Theme', selected: null } dropdown = React.createRef() componentDidMount() { const { queryState } = getRouteState(this.props.router) const queryHighlights = queryState ? Object.keys(queryState) .filter(key => HIGHLIGHT_KEYS.includes(key)) .reduce((obj, key) => ({ ...obj, [key]: queryState[key] }), {}) : {} const storedThemes = getThemes(localStorage) || [] this.setState(({ themes }) => { const newThemes = [...storedThemes, ...themes] const name = getCustomName(newThemes) this.selectedTheme = newThemes.find(({ id }) => id === this.props.theme) || DEFAULT_THEME const highlights = { ...this.selectedTheme.highlights, ...queryHighlights } this.props.onChange('highlights', highlights) return { themes: newThemes, highlights, name } }) } componentDidUpdate(prevProps) { const { isVisible, theme, onChange } = this.props const { themes } = this.state if (prevProps.isVisible && !isVisible) { this.setState({ name: getCustomName(themes) }) onChange('highlights', themes.find(({ id }) => id === theme).highlights) } } applyPreset = preset => { this.setState(({ themes }) => { this.props.onChange('highlights', themes.find(({ id }) => id === preset).highlights) return { preset } }) } handleChange = ({ id }) => { const { theme, toggleVisibility, onChange } = this.props const { themes } = this.state if (id === 'create') { toggleVisibility() this.dropdown.current.closeMenu() } else { onChange('theme', id) onChange('highlights', themes.find(({ id }) => id === theme).highlights) } } updateName = ({ target: { value: name } }) => this.setState({ name }) selectHighlight = highlight => () => this.setState(({ selected }) => ({ selected: selected === highlight ? null : highlight })) updateHighlight = ({ rgb }) => this.props.onChange('highlights', { ...this.props.highlights, [this.state.selected]: stringifyRGBA(rgb) }) removeTheme = id => event => { event.stopPropagation() const { themes } = this.state const newThemes = themes.filter(t => t.id !== id) saveThemes(localStorage, newThemes.filter(({ custom }) => custom)) if (this.props.theme === id) { this.props.onChange('theme', DEFAULT_THEME.id) this.props.onChange('highlights', DEFAULT_THEME.highlights) } else { this.setState({ themes: newThemes }) } } createTheme = () => { const { highlights } = this.props const { themes, name } = this.state const id = `theme:${generateId()}` const newTheme = { id, name, highlights, custom: true } const customThemes = [newTheme, ...themes.filter(({ custom }) => custom)] saveThemes(localStorage, customThemes) this.props.onChange('theme', id) } itemWrapper = props => render() { const { theme, isVisible, toggleVisibility, highlights } = this.props const { name, themes, selected, preset } = this.state const dropdownValue = isVisible ? { name } : { id: theme, name: this.selectedTheme.name } const dropdownList = [ { id: 'create', name: 'Create +' }, ...themes ] return (
{isVisible && ( )}
) } } export default managePopout(withRouter(Themes))