From 4dea5661938ae45eec91b2570690ab004670699f Mon Sep 17 00:00:00 2001 From: raboid Date: Thu, 11 Apr 2019 17:57:24 -0400 Subject: [PATCH] rework logic --- components/Carbon.js | 5 +- components/Editor.js | 84 ++++++++- components/Themes/ThemeCreate.js | 283 ++++++++++++++++--------------- components/Themes/index.js | 151 +++++------------ lib/constants.js | 2 +- lib/routing.js | 10 ++ pages/index.js | 10 +- 7 files changed, 275 insertions(+), 270 deletions(-) diff --git a/components/Carbon.js b/components/Carbon.js index b899a50..5d0fd80 100644 --- a/components/Carbon.js +++ b/components/Carbon.js @@ -12,7 +12,6 @@ import { LANGUAGE_MODE_HASH, LANGUAGE_NAME_HASH, LANGUAGE_MIME_HASH, - THEMES_HASH, DEFAULT_SETTINGS } from '../lib/constants' @@ -77,7 +76,7 @@ class Carbon extends React.PureComponent { const options = { lineNumbers: config.lineNumbers, mode: languageMode || 'plaintext', - theme: config.theme, + theme: config.theme.id, scrollBarStyle: null, viewportMargin: Infinity, lineWrapping: true, @@ -108,7 +107,7 @@ class Carbon extends React.PureComponent { value={this.props.children} options={options} /> - {config.watermark && } + {config.watermark && }
diff --git a/components/Editor.js b/components/Editor.js index cbec0f8..c0b396e 100644 --- a/components/Editor.js +++ b/components/Editor.js @@ -25,10 +25,12 @@ import { DEFAULT_CODE, DEFAULT_SETTINGS, DEFAULT_LANGUAGE, - DEFAULT_PRESET_ID + DEFAULT_PRESET_ID, + DEFAULT_THEME, + THEMES } from '../lib/constants' import { serializeState, getRouteState } from '../lib/routing' -import { getSettings, unescapeHtml, formatCode, omit } from '../lib/util' +import { getThemes, saveThemes, getSettings, unescapeHtml, formatCode, omit } from '../lib/util' import LanguageIcon from './svg/Language' const languageIcon = @@ -44,8 +46,8 @@ class Editor extends React.Component { super(props) this.state = { ...DEFAULT_SETTINGS, + themes: THEMES, preset: DEFAULT_PRESET_ID, - highlights: {}, loading: true } @@ -81,6 +83,25 @@ class Editor extends React.Component { loading: false } + const storedThemes = getThemes(localStorage) + + newState.themes = storedThemes + ? [...storedThemes, ...this.state.themes] + : [...this.state.themes] + + if (newState.theme) { + newState.theme = newState.themes.find(t => t.id === newState.theme) || DEFAULT_THEME + } + + if (newState.highlights) { + newState.theme = { + ...newState.theme, + highlights: newState.highlights + } + + delete newState.highlights + } + // Makes sure the slash in 'application/X' is decoded if (newState.language) { newState.language = unescapeHtml(newState.language) @@ -99,7 +120,10 @@ class Editor extends React.Component { updateState = updates => { this.setState(updates, () => { if (!this.gist) { - this.props.onUpdate(this.state) + this.props.onUpdate({ + ...this.state, + theme: this.state.theme.id + }) } }) } @@ -117,7 +141,16 @@ class Editor extends React.Component { // if safari, get image from api const isPNG = format !== 'svg' if (this.context.image && this.isSafari && isPNG) { - const encodedState = serializeState(this.state) + const state = { + ...this.state, + theme: this.state.theme.id, + highlights: this.state.theme.highlights + } + + delete state.themes + + const encodedState = serializeState(state) + return this.context.image(encodedState) } @@ -260,6 +293,35 @@ class Editor extends React.Component { } } + updateTheme = theme => this.updateState({ theme }) + + createTheme = theme => + this.setState(({ themes }) => { + const newThemes = [theme, ...themes] + + saveThemes(localStorage, newThemes.filter(({ custom }) => custom)) + + return { + theme, + themes: newThemes + } + }) + + removeTheme = id => + this.setState(({ themes, theme }) => { + const newState = { + themes: themes.filter(t => t.id !== id) + } + + saveThemes(localStorage, newState.themes.filter(({ custom }) => custom)) + + if (theme.id === id) { + newState.theme = DEFAULT_THEME + } + + return newState + }) + format = () => formatCode(this.state.code) .then(this.updateCode) @@ -267,12 +329,10 @@ class Editor extends React.Component { // create toast here in the future }) - applyPreset = ({ id: preset, ...settings }) => this.updateState({ preset, ...settings }) - render() { const { theme, - highlights, + themes, language, backgroundColor, backgroundImage, @@ -286,7 +346,13 @@ class Editor extends React.Component { return (
- + (
) -const ThemeCreate = ({ - theme, - themes, - highlights, - name, - preset, - selected, - createTheme, - applyPreset, - updateName, - selectHighlight, - updateHighlight -}) => ( - -
-
- Name - -
-
- + `Custom Theme ${themes.filter(({ name }) => name.startsWith('Custom Theme')).length + 1}` + +const ThemeCreate = ({ theme, themes, highlights, create, updateHighlights }) => { + const [preset, updatePreset] = React.useState(theme.id) + const [highlight, selectHighlight] = React.useState() + const [name, updateName] = React.useState(getCustomName(themes)) + + return ( + +
+
+ Name + updateName(value)} + maxLength="32" + /> +
+
+ selectHighlight(null)} + onChange={id => { + updatePreset(id) + updateHighlights(themes.find(t => t.id === id).highlights) + }} + > + {({ name }) => {name}} + +
+
+ {HIGHLIGHT_KEYS.map(key => ( +
+ +
+ ))} +
+
-
- {HIGHLIGHT_KEYS.map(key => ( -
- -
- ))} + Create + +
- -
- {selected && ( - - )} - - -) + {highlight && ( + updateHighlights({ [highlight]: stringifyRGBA(rgb) })} + /> + )} + + + ) +} export default ThemeCreate diff --git a/components/Themes/index.js b/components/Themes/index.js index 9e4348b..b77edf6 100644 --- a/components/Themes/index.js +++ b/components/Themes/index.js @@ -5,18 +5,25 @@ import Dropdown from '../Dropdown' import { managePopout } from '../Popout' import ThemeIcon from '../svg/Theme' import RemoveIcon from '../svg/Remove' -import { THEMES, COLORS, DEFAULT_THEME } from '../../lib/constants' -import { getThemes, saveThemes, stringifyRGBA, generateId } from '../../lib/util' +import { COLORS } from '../../lib/constants' const ThemeCreate = dynamic(() => import('./ThemeCreate'), { loading: () => null }) -const ThemeItem = ({ children, item, isSelected, onClick }) => ( +const ThemeItem = ({ children, item, isSelected, remove }) => (
{children} {item.custom && !isSelected && ( -
+
{ + e.stopPropagation() + remove(item.id) + }} + >
)} @@ -40,131 +47,58 @@ const ThemeItem = ({ children, item, isSelected, onClick }) => ( 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, - input: 'Custom Theme', - selected: null + highlights: {} } dropdown = React.createRef() - componentDidMount() { - const { update, theme, highlights } = this.props - const storedThemes = getThemes(localStorage) || [] - - this.setState(({ themes }) => { - const newThemes = [...storedThemes, ...themes] - - this.selectedTheme = newThemes.find(({ id }) => id === theme) || DEFAULT_THEME - - if (Object.keys(highlights).length === 0) { - update({ highlights: this.selectedTheme.highlights }) - } - - return { - themes: newThemes, - input: getCustomName(newThemes) - } - }) - } - componentDidUpdate(prevProps) { - const { isVisible, theme, update } = this.props - const { themes } = this.state - - if (prevProps.isVisible && !isVisible) { - this.setState({ input: getCustomName(themes) }) - update({ highlights: themes.find(({ id }) => id === theme).highlights }) + if (prevProps.isVisible && !this.props.isVisible) { + this.setState({ + highlights: {} + }) } } - applyPreset = preset => { - this.setState(({ themes }) => { - this.props.update({ highlights: themes.find(({ id }) => id === preset).highlights }) - return { - preset - } - }) - } - - handleChange = ({ id }) => { + handleThemeSelected = theme => { const { toggleVisibility, update } = this.props - const { themes } = this.state - - if (id === 'create') { + if (theme.id === 'create') { toggleVisibility() this.dropdown.current.closeMenu() } else { - update({ theme: id, highlights: themes.find(theme => theme.id === id).highlights }) + update(theme) } } - updateInput = ({ target: { value: input } }) => this.setState({ input }) - - selectHighlight = highlight => () => - this.setState(({ selected }) => ({ - selected: selected === highlight ? null : highlight + selectHighlight = key => () => + this.setState(({ selectedHighlight }) => ({ + selectedHighlight: selectedHighlight === key ? null : key })) - updateHighlight = ({ rgb }) => - this.props.update({ + updateHighlights = updates => + this.setState(({ highlights }) => ({ highlights: { - ...this.props.highlights, - [this.state.selected]: stringifyRGBA(rgb) + ...highlights, + ...updates } - }) - - removeTheme = id => event => { - const { themes } = this.state - const { theme, update } = this.props - - event.stopPropagation() - - const newThemes = themes.filter(t => t.id !== id) - - saveThemes(localStorage, newThemes.filter(({ custom }) => custom)) - - if (theme === id) { - update({ theme: DEFAULT_THEME.id, highlights: DEFAULT_THEME.highlights }) - } else { - this.setState({ themes: newThemes }) - } - } - - createTheme = () => { - const { highlights, update } = this.props - const { themes, input: name } = this.state - - const id = `theme:${generateId()}` - - const newTheme = { - id, - name, - highlights, - custom: true - } - - const customThemes = [newTheme, ...themes.filter(({ custom }) => custom)] - - saveThemes(localStorage, customThemes) + })) - update({ theme: id }) + create = theme => { + this.props.toggleVisibility() + this.props.create(theme) } - itemWrapper = props => + itemWrapper = props => render() { - const { theme, isVisible, toggleVisibility, highlights } = this.props - const { input, themes, selected, preset } = this.state + const { themes, theme, isVisible, toggleVisibility } = this.props + const { input } = this.state + + const highlights = { ...theme.highlights, ...this.state.highlights } - const dropdownValue = isVisible ? { name: input } : { id: theme, name: this.selectedTheme.name } + const dropdownValue = isVisible ? { name: input } : { id: theme.id, name: theme.name } const dropdownList = [ { @@ -184,23 +118,16 @@ class Themes extends React.PureComponent { selected={dropdownValue} list={dropdownList} itemWrapper={this.itemWrapper} - onChange={this.handleChange} + onChange={this.handleThemeSelected} onOpen={isVisible && toggleVisibility} /> {isVisible && ( )}