import { Button, Callout, Checkbox, FormGroup, MenuItem, } from '@blueprintjs/core'; import * as React from 'react'; import * as fs from 'fs-extra'; import * as namor from 'namor'; import * as path from 'path'; import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select'; import { observer } from 'mobx-react'; import { reaction } from 'mobx'; import { shell } from 'electron'; import { highlightText } from '../../utils/highlight-text'; import { AppState } from '../state'; import { getAvailableThemes, getTheme, THEMES_PATH } from '../themes'; import { LoadedFiddleTheme } from '../themes-defaults'; const ThemeSelect = Select.ofType(); /** * Helper method: Returns the for Electron * versions. * * @param {RunnableVersion} item * @param {IItemRendererProps} { handleClick, modifiers, query } * @returns */ export const renderItem: ItemRenderer = ( item, { handleClick, modifiers, query }, ) => { if (!modifiers.matchesPredicate) { return null; } return ( ); }; interface AppearanceSettingsProps { appState: AppState; toggleHasPopoverOpen: () => void; } interface AppearanceSettingsState { themes: Array; selectedTheme?: LoadedFiddleTheme; } /** * Settings content to manage GitHub-related preferences. * * @class GitHubSettings * @extends {React.Component} */ @observer export class AppearanceSettings extends React.Component< AppearanceSettingsProps, AppearanceSettingsState > { public constructor(props: AppearanceSettingsProps) { super(props); this.handleChange = this.handleChange.bind(this); this.openThemeFolder = this.openThemeFolder.bind(this); this.handleAddTheme = this.handleAddTheme.bind(this); this.handleThemeSource = this.handleThemeSource.bind(this); this.state = { themes: [], }; getAvailableThemes().then((themes) => { const { theme } = this.props.appState; const selectedTheme = (theme && themes.find(({ file }) => file === theme)) || themes[0]; this.setState({ themes, selectedTheme }); // set up mobx so that changes from system sync are reflected in picker reaction( () => this.props.appState.theme, async () => { const selectedTheme = await getTheme(this.props.appState.theme); this.setState({ selectedTheme }); }, ); }); this.createNewThemeFromCurrent = this.createNewThemeFromCurrent.bind(this); this.openThemeFolder = this.openThemeFolder.bind(this); } /** * Handle change, which usually means that we'd like update * the current theme. * * @param {LoadedFiddleTheme} theme */ public handleChange(theme: LoadedFiddleTheme) { this.setState({ selectedTheme: theme }); this.props.appState.setTheme(theme.file); } /** * Creates a new theme from the current template. * * @returns {Promise} * @memberof AppearanceSettings */ public async createNewThemeFromCurrent(): Promise { const { appState } = this.props; const theme = await getTheme(appState.theme); try { const name = namor.generate({ words: 2, numbers: 0 }); const themePath = path.join(THEMES_PATH, `${name}.json`); await fs.outputJSON( themePath, { ...theme, name, file: undefined, css: undefined, }, { spaces: 2 }, ); shell.showItemInFolder(themePath); this.setState({ themes: await getAvailableThemes() }); return true; } catch (error) { console.warn(`Themes: Failed to create new theme from current`, error); return false; } } /** * Creates the themes folder in .electron-fiddle if one does not * exist yet, then shows that folder in the Finder/Explorer. * * @returns {Promise} */ public async openThemeFolder(): Promise { try { await fs.ensureDir(THEMES_PATH); await shell.showItemInFolder(THEMES_PATH); return true; } catch (error) { console.warn(`Appearance Settings: Could not open themes folder`); return false; } } public render() { const { selectedTheme } = this.state; const { isUsingSystemTheme } = this.props.appState; const selectedName = (selectedTheme && selectedTheme.name) || 'Select a theme'; return (

Appearance

this.props.toggleHasPopoverOpen(), }} noResults={} >
); } /** * Opens the "add monaco theme" dialog */ public handleAddTheme(): void { this.props.appState.toggleAddMonacoThemeDialog(); } public handleThemeSource(event: React.FormEvent): void { const { appState } = this.props; const { checked } = event.currentTarget; appState.isUsingSystemTheme = checked; } }