support theme highlights in query string

main
raboid 6 years ago committed by Michael Fix
parent 512b53beee
commit 2ae529e404

@ -45,13 +45,13 @@ class Editor extends React.Component {
this.state = { this.state = {
...DEFAULT_SETTINGS, ...DEFAULT_SETTINGS,
preset: DEFAULT_PRESET_ID, preset: DEFAULT_PRESET_ID,
highlights: {},
loading: true loading: true
} }
this.export = this.export.bind(this) this.export = this.export.bind(this)
this.upload = this.upload.bind(this) this.upload = this.upload.bind(this)
this.updateSetting = this.updateSetting.bind(this) this.updateSetting = this.updateSetting.bind(this)
this.updateTheme = this.updateTheme.bind(this)
this.updateLanguage = this.updateLanguage.bind(this) this.updateLanguage = this.updateLanguage.bind(this)
this.updateBackground = this.updateBackground.bind(this) this.updateBackground = this.updateBackground.bind(this)
this.resetDefaultSettings = this.resetDefaultSettings.bind(this) this.resetDefaultSettings = this.resetDefaultSettings.bind(this)
@ -86,7 +86,7 @@ class Editor extends React.Component {
newState.language = unescapeHtml(newState.language) newState.language = unescapeHtml(newState.language)
} }
this.updateState(newState) this.setState(newState)
this.isSafari = this.isSafari =
window.navigator && window.navigator &&
@ -112,7 +112,8 @@ class Editor extends React.Component {
// if safari, get image from api // if safari, get image from api
const isPNG = format !== 'svg' const isPNG = format !== 'svg'
if (this.context.image && this.isSafari && isPNG) { if (this.context.image && this.isSafari && isPNG) {
const encodedState = serializeState(this.state) const { highlights, ...state } = this.state
const encodedState = serializeState({ ...state, ...highlights })
return this.context.image(encodedState) return this.context.image(encodedState)
} }
@ -239,10 +240,6 @@ class Editor extends React.Component {
} }
} }
updateTheme(theme) {
this.updateSetting('theme', theme)
}
updateLanguage(language) { updateLanguage(language) {
this.updateSetting('language', language.mime || language.mode) this.updateSetting('language', language.mime || language.mode)
} }
@ -271,6 +268,7 @@ class Editor extends React.Component {
render() { render() {
const { const {
theme, theme,
highlights,
language, language,
backgroundColor, backgroundColor,
backgroundImage, backgroundImage,
@ -284,7 +282,13 @@ class Editor extends React.Component {
return ( return (
<div className="editor"> <div className="editor">
<Toolbar> <Toolbar>
<Themes key={theme} updateTheme={this.updateTheme} theme={theme} /> <Themes
ref={this.themes}
key={theme}
onChange={this.updateSetting}
theme={theme}
highlights={highlights}
/>
<Dropdown <Dropdown
icon={languageIcon} icon={languageIcon}
selected={ selected={

@ -1,12 +1,14 @@
import React from 'react' import React from 'react'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import { withRouter } from 'next/router'
import Dropdown from '../Dropdown' import Dropdown from '../Dropdown'
import { managePopout } from '../Popout' import { managePopout } from '../Popout'
import ThemeIcon from '../svg/Theme' import ThemeIcon from '../svg/Theme'
import RemoveIcon from '../svg/Remove' import RemoveIcon from '../svg/Remove'
import { THEMES, COLORS, DEFAULT_THEME } from '../../lib/constants' import { THEMES, COLORS, DEFAULT_THEME, HIGHLIGHT_KEYS } from '../../lib/constants'
import { getThemes, saveThemes, stringifyRGBA, generateId } from '../../lib/util' import { getThemes, saveThemes, stringifyRGBA, generateId } from '../../lib/util'
import { getRouteState } from '../../lib/routing'
const ThemeCreate = dynamic(() => import('./ThemeCreate'), { const ThemeCreate = dynamic(() => import('./ThemeCreate'), {
loading: () => null loading: () => null
@ -40,13 +42,15 @@ const ThemeItem = ({ children, item, isSelected, onClick }) => (
const themeIcon = <ThemeIcon /> const themeIcon = <ThemeIcon />
const getCustomName = themes =>
`Custom Theme ${themes.filter(({ name }) => name.startsWith('Custom Theme')).length + 1}`
class Themes extends React.PureComponent { class Themes extends React.PureComponent {
selectedTheme = DEFAULT_THEME selectedTheme = DEFAULT_THEME
state = { state = {
themes: THEMES, themes: THEMES,
preset: this.props.theme, preset: this.props.theme,
highlights: {},
name: 'Custom Theme', name: 'Custom Theme',
selected: null selected: null
} }
@ -54,36 +58,67 @@ class Themes extends React.PureComponent {
dropdown = React.createRef() dropdown = React.createRef()
componentDidMount() { 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) || [] const storedThemes = getThemes(localStorage) || []
this.setState(({ themes }) => { this.setState(({ themes }) => {
const newThemes = [...storedThemes, ...themes] const newThemes = [...storedThemes, ...themes]
const name = `Custom Theme ${newThemes.filter(({ name }) => name.startsWith('Custom Theme')) const name = getCustomName(newThemes)
.length + 1}`
this.selectedTheme = newThemes.find(({ id }) => id === this.props.theme) || DEFAULT_THEME this.selectedTheme = newThemes.find(({ id }) => id === this.props.theme) || DEFAULT_THEME
const highlights = {
...this.selectedTheme.highlights,
...queryHighlights
}
this.props.onChange('highlights', highlights)
return { return {
themes: newThemes, themes: newThemes,
highlights: this.selectedTheme.highlights, highlights,
name name
} }
}) })
} }
applyPreset = preset => componentDidUpdate(prevProps) {
this.setState(({ themes }) => ({ const { isVisible, theme, onChange } = this.props
preset, const { themes } = this.state
highlights: themes.find(({ id }) => id === preset).highlights
})) 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 }) => { handleChange = ({ id }) => {
const { theme, toggleVisibility, onChange } = this.props
const { themes } = this.state
if (id === 'create') { if (id === 'create') {
this.props.toggleVisibility() toggleVisibility()
this.dropdown.current.closeMenu() this.dropdown.current.closeMenu()
} else { } else {
this.props.updateTheme(id) onChange('theme', id)
onChange('highlights', themes.find(({ id }) => id === theme).highlights)
} }
} }
@ -95,11 +130,9 @@ class Themes extends React.PureComponent {
})) }))
updateHighlight = ({ rgb }) => updateHighlight = ({ rgb }) =>
this.setState({ this.props.onChange('highlights', {
highlights: { ...this.props.highlights,
...this.state.highlights, [this.state.selected]: stringifyRGBA(rgb)
[this.state.selected]: stringifyRGBA(rgb)
}
}) })
removeTheme = id => event => { removeTheme = id => event => {
@ -112,14 +145,16 @@ class Themes extends React.PureComponent {
saveThemes(localStorage, newThemes.filter(({ custom }) => custom)) saveThemes(localStorage, newThemes.filter(({ custom }) => custom))
if (this.props.theme === id) { if (this.props.theme === id) {
this.props.updateTheme(DEFAULT_THEME.id) this.props.onChange('theme', DEFAULT_THEME.id)
this.props.onChange('highlights', DEFAULT_THEME.highlights)
} else { } else {
this.setState({ themes: newThemes }) this.setState({ themes: newThemes })
} }
} }
createTheme = () => { createTheme = () => {
const { themes, name, highlights } = this.state const { highlights } = this.props
const { themes, name } = this.state
const id = `theme:${generateId()}` const id = `theme:${generateId()}`
@ -134,14 +169,14 @@ class Themes extends React.PureComponent {
saveThemes(localStorage, customThemes) saveThemes(localStorage, customThemes)
this.props.updateTheme(id) this.props.onChange('theme', id)
} }
itemWrapper = props => <ThemeItem {...props} onClick={this.removeTheme} /> itemWrapper = props => <ThemeItem {...props} onClick={this.removeTheme} />
render() { render() {
const { theme, isVisible, toggleVisibility } = this.props const { theme, isVisible, toggleVisibility, highlights } = this.props
const { name, themes, highlights, selected, preset } = this.state const { name, themes, selected, preset } = this.state
const dropdownValue = isVisible ? { name } : { id: theme, name: this.selectedTheme.name } const dropdownValue = isVisible ? { name } : { id: theme, name: this.selectedTheme.name }
@ -255,4 +290,4 @@ class Themes extends React.PureComponent {
} }
} }
export default managePopout(Themes) export default managePopout(withRouter(Themes))

@ -35,7 +35,19 @@ const mappings = [
{ field: 'wm:watermark', type: 'bool' }, { field: 'wm:watermark', type: 'bool' },
{ field: 'copy', type: 'bool' }, { field: 'copy', type: 'bool' },
{ field: 'readonly', type: 'bool' }, { field: 'readonly', type: 'bool' },
{ field: 'id' } { field: 'id' },
{ field: 'text' },
{ field: 'meta' },
{ field: 'tbg:background' },
{ field: 'var:variable' },
{ field: 'attr:attribute' },
{ field: 'def:definition' },
{ field: 'kw:keyword' },
{ field: 'op:operator' },
{ field: 'prop:property' },
{ field: 'num:number' },
{ field: 'str:string' },
{ field: 'cmt:comment' }
] ]
const reverseMappings = mappings.map(mapping => const reverseMappings = mappings.map(mapping =>

Loading…
Cancel
Save