diff --git a/app/common/constants.js b/app/common/constants.js index 1d2cb4eddf..1a9fbd4207 100644 --- a/app/common/constants.js +++ b/app/common/constants.js @@ -35,7 +35,7 @@ export function getClientString () { } // Global Stuff -export const DB_PERSIST_INTERVAL = 1000 * 60 * 10; +export const DB_PERSIST_INTERVAL = 1000 * 30; export const DEBOUNCE_MILLIS = 100; export const MAX_RESPONSES = 20; export const REQUEST_TIME_TO_SHOW_COUNTER = 1; // Seconds diff --git a/app/static/themes/dark.png b/app/static/themes/dark.png index a14d22803a..7888eac68f 100644 Binary files a/app/static/themes/dark.png and b/app/static/themes/dark.png differ diff --git a/app/static/themes/default.png b/app/static/themes/default.png index 301f6557f1..5a33dd106c 100644 Binary files a/app/static/themes/default.png and b/app/static/themes/default.png differ diff --git a/app/static/themes/light.png b/app/static/themes/light.png index 54f7768c40..ad1729a548 100644 Binary files a/app/static/themes/light.png and b/app/static/themes/light.png differ diff --git a/app/static/themes/material.png b/app/static/themes/material.png new file mode 100644 index 0000000000..53e096c802 Binary files /dev/null and b/app/static/themes/material.png differ diff --git a/app/static/themes/purple.png b/app/static/themes/purple.png new file mode 100644 index 0000000000..d16d0614bb Binary files /dev/null and b/app/static/themes/purple.png differ diff --git a/app/static/themes/railscasts.png b/app/static/themes/railscasts.png new file mode 100644 index 0000000000..7d4b76e615 Binary files /dev/null and b/app/static/themes/railscasts.png differ diff --git a/app/static/themes/solarized-dark.png b/app/static/themes/solarized-dark.png new file mode 100644 index 0000000000..fea9a213e1 Binary files /dev/null and b/app/static/themes/solarized-dark.png differ diff --git a/app/static/themes/solarized-light.png b/app/static/themes/solarized-light.png new file mode 100644 index 0000000000..4a1a83ed6f Binary files /dev/null and b/app/static/themes/solarized-light.png differ diff --git a/app/static/themes/solarized.png b/app/static/themes/solarized.png new file mode 100644 index 0000000000..d93168c4b3 Binary files /dev/null and b/app/static/themes/solarized.png differ diff --git a/app/sync/session.js b/app/sync/session.js index 9d39c40fa1..6648fcc93c 100644 --- a/app/sync/session.js +++ b/app/sync/session.js @@ -3,8 +3,6 @@ import * as crypt from './crypt'; import * as util from '../common/fetch'; import {trackEvent, setAccountId} from '../analytics'; -const NO_SESSION = '__NO_SESSION__'; - /** Create a new Account for the user */ export async function signup (firstName, lastName, rawEmail, rawPassphrase) { @@ -210,7 +208,7 @@ export function getPrivateKey () { } export function getCurrentSessionId () { - return localStorage.getItem('currentSessionId') || NO_SESSION; + return localStorage.getItem('currentSessionId'); } export function getAccountId () { @@ -236,7 +234,7 @@ export function getFullName () { */ export function getSessionData () { const sessionId = getCurrentSessionId(); - if (sessionId == NO_SESSION) { + if (!sessionId) { return {}; } @@ -279,7 +277,7 @@ export function unsetSessionData () { /** Check if we (think) we have a session */ export function isLoggedIn () { - return getCurrentSessionId() !== NO_SESSION; + return getCurrentSessionId(); } /** Log out and delete session data */ @@ -305,12 +303,12 @@ export async function endTrial () { trackEvent('Session', 'End Trial'); } -function whoami (sessionId = null) { +export function whoami (sessionId = null) { return util.get('/auth/whoami', sessionId); } export function getSessionKey (sessionId) { - return `session__${sessionId.slice(0, 10)}` + return `session__${(sessionId || '').slice(0, 10)}` } // ~~~~~~~~~~~~~~~~ // diff --git a/app/ui/components/ResponsePane.js b/app/ui/components/ResponsePane.js index 3c54ba5090..6f3fa91692 100644 --- a/app/ui/components/ResponsePane.js +++ b/app/ui/components/ResponsePane.js @@ -111,7 +111,7 @@ class ResponsePane extends Component { return (
@@ -158,7 +158,7 @@ class ResponsePane extends Component { return (
diff --git a/app/ui/components/Wrapper.js b/app/ui/components/Wrapper.js index fdf5a698d2..c41e352f00 100644 --- a/app/ui/components/Wrapper.js +++ b/app/ui/components/Wrapper.js @@ -286,11 +286,13 @@ class Wrapper extends Component { workspace={activeWorkspace}/> + onChange={models.workspace.update} + editorFontSize={settings.editorFontSize} + /> ) } diff --git a/app/ui/components/base/Button.js b/app/ui/components/base/Button.js index 10afab3e48..4c062f6d20 100644 --- a/app/ui/components/base/Button.js +++ b/app/ui/components/base/Button.js @@ -3,16 +3,13 @@ import {shell} from 'electron'; class Button extends Component { _handleClick = e => { - const {onClick, disabled} = this.props; - - if (!onClick || disabled) { - return; - } + const {onClick, onDisabledClick, disabled} = this.props; + const fn = disabled ? onDisabledClick : onClick; if (this.props.hasOwnProperty('value')) { - onClick(this.props.value, e); + fn && fn(this.props.value, e); } else { - onClick(e); + fn && fn(e); } }; @@ -26,6 +23,8 @@ class Button extends Component { Button.propTypes = { value: PropTypes.any, + onDisabledClick: PropTypes.func, + onClick: PropTypes.func, }; export default Button; diff --git a/app/ui/components/base/Modal.js b/app/ui/components/base/Modal.js index 1ffdf4618e..04577ef41a 100644 --- a/app/ui/components/base/Modal.js +++ b/app/ui/components/base/Modal.js @@ -119,7 +119,7 @@ class Modal extends Component { style={{zIndex: zIndex}} onClick={this._handleClick}>
-
this.hide()}>
+
this.hide()}>
{this.props.children}
diff --git a/app/ui/components/base/dropdown/Dropdown.js b/app/ui/components/base/dropdown/Dropdown.js index 8514892210..3d52cd77f1 100644 --- a/app/ui/components/base/dropdown/Dropdown.js +++ b/app/ui/components/base/dropdown/Dropdown.js @@ -137,7 +137,7 @@ class Dropdown extends Component { } else { finalChildren = [ dropdownButtons[0], -
    +
      {dropdownItems}
    ] diff --git a/app/ui/components/dropdowns/WorkspaceDropdown.js b/app/ui/components/dropdowns/WorkspaceDropdown.js index 882844bc3c..5358611a75 100644 --- a/app/ui/components/dropdowns/WorkspaceDropdown.js +++ b/app/ui/components/dropdowns/WorkspaceDropdown.js @@ -82,7 +82,7 @@ class WorkspaceDropdown extends Component {

    - {isLoading ? : null} + {isLoading ? : null} {" "}
    @@ -113,7 +113,7 @@ class WorkspaceDropdown extends Component { Insomnia Version {getAppVersion()} - App Preferences + Preferences diff --git a/app/ui/components/editors/CookiesEditor.js b/app/ui/components/editors/CookiesEditor.js index 0b64cb84da..6c3cec8180 100644 --- a/app/ui/components/editors/CookiesEditor.js +++ b/app/ui/components/editors/CookiesEditor.js @@ -1,6 +1,7 @@ import React, {PropTypes, Component} from 'react'; import {Cookie} from 'tough-cookie'; +import PromptButton from '../base/PromptButton'; import CookieInput from '../CookieInput'; import {cookieToString} from '../../../common/cookies'; @@ -60,11 +61,13 @@ class CookiesEditor extends Component { - + ) @@ -72,18 +75,18 @@ class CookiesEditor extends Component { {cookies.length === 0 ? ( -
    -

    - I couldn't find any cookies for you. -

    -

    - -

    -
    - ) : null} +
    +

    + I couldn't find any cookies for you. +

    +

    + +

    +
    + ) : null} ); } diff --git a/app/ui/components/editors/EnvironmentEditor.js b/app/ui/components/editors/EnvironmentEditor.js index fe4ceeb57c..adfba0afc3 100644 --- a/app/ui/components/editors/EnvironmentEditor.js +++ b/app/ui/components/editors/EnvironmentEditor.js @@ -22,11 +22,12 @@ class EnvironmentEditor extends Component { } render () { - const {environment, ...props} = this.props; + const {environment, editorFontSize, ...props} = this.props; return (

    - +

    Select a body type from above

    diff --git a/app/ui/components/modals/EnvironmentEditModal.js b/app/ui/components/modals/EnvironmentEditModal.js index 6d0fe661ad..aeb5a54232 100644 --- a/app/ui/components/modals/EnvironmentEditModal.js +++ b/app/ui/components/modals/EnvironmentEditModal.js @@ -45,13 +45,15 @@ class EnvironmentEditModal extends Component { } render () { + const {editorFontSize, ...extraProps} = this.props; const {requestGroup, isValid} = this.state; return ( - this.modal = m} tall={true} top={true} {...this.props}> + this.modal = m} tall={true} top={true} {...extraProps}> Environment Overrides (JSON Format) this._envEditor = node} key={requestGroup ? requestGroup._id : 'n/a'} environment={requestGroup ? requestGroup.environment : {}} @@ -73,7 +75,8 @@ class EnvironmentEditModal extends Component { } EnvironmentEditModal.propTypes = { - onChange: PropTypes.func.isRequired + onChange: PropTypes.func.isRequired, + editorFontSize: PropTypes.number.isRequired, }; export default EnvironmentEditModal; diff --git a/app/ui/components/modals/GenerateCodeModal.js b/app/ui/components/modals/GenerateCodeModal.js index d80feabe8f..5d125dd71c 100644 --- a/app/ui/components/modals/GenerateCodeModal.js +++ b/app/ui/components/modals/GenerateCodeModal.js @@ -95,6 +95,7 @@ class GenerateCodeModal extends Component { render () { const {cmd, target, client} = this.state; + const {editorFontSize} = this.props; const targets = availableTargets(); @@ -145,6 +146,7 @@ class GenerateCodeModal extends Component { key={Date.now()} mode={MODE_MAP[target.key] || target.key} ref={n => this._editor = n} + fontSize={editorFontSize} lightTheme={true} lineWrapping={true} value={cmd} @@ -165,6 +167,7 @@ class GenerateCodeModal extends Component { GenerateCodeModal.propTypes = { environmentId: PropTypes.string.isRequired, + editorFontSize: PropTypes.number.isRequired, }; export default GenerateCodeModal; diff --git a/app/ui/components/modals/SettingsModal.js b/app/ui/components/modals/SettingsModal.js index 8be340ccde..ffaca49227 100644 --- a/app/ui/components/modals/SettingsModal.js +++ b/app/ui/components/modals/SettingsModal.js @@ -27,6 +27,12 @@ class SettingsModal extends Component { models.settings.update(this.props.settings, {theme}); }; + componentDidMount () { + // Hacky way to set theme on launch + // TODO: move somewhere else + this._handleChangeTheme(this.props.settings.theme); + } + show (currentTabIndex = 0) { this.setState({currentTabIndex}); this.modal.show(); @@ -76,8 +82,8 @@ class SettingsModal extends Component { - diff --git a/app/ui/components/modals/WorkspaceEnvironmentsEditModal.js b/app/ui/components/modals/WorkspaceEnvironmentsEditModal.js index 9ed0c08fe7..c1a3c5e0e9 100644 --- a/app/ui/components/modals/WorkspaceEnvironmentsEditModal.js +++ b/app/ui/components/modals/WorkspaceEnvironmentsEditModal.js @@ -139,6 +139,7 @@ class WorkspaceEnvironmentsEditModal extends Component { } render () { + const {editorFontSize} = this.props; const {subEnvironments, rootEnvironment, isValid, forceRefreshKey} = this.state; const activeEnvironment = this._getActiveEnvironment(); @@ -199,6 +200,7 @@ class WorkspaceEnvironmentsEditModal extends Component {
    this._envEditor = n} key={`${forceRefreshKey}::${(activeEnvironment ? activeEnvironment._id : 'n/a')}`} environment={activeEnvironment ? activeEnvironment.data : {}} @@ -226,7 +228,8 @@ class WorkspaceEnvironmentsEditModal extends Component { } WorkspaceEnvironmentsEditModal.propTypes = { - onChange: PropTypes.func.isRequired + onChange: PropTypes.func.isRequired, + editorFontSize: PropTypes.number.isRequired, }; export default WorkspaceEnvironmentsEditModal; diff --git a/app/ui/components/settings/SettingsTheme.js b/app/ui/components/settings/SettingsTheme.js index ec0d251b07..e046cf8d71 100644 --- a/app/ui/components/settings/SettingsTheme.js +++ b/app/ui/components/settings/SettingsTheme.js @@ -1,42 +1,107 @@ import React, {Component, PropTypes} from 'react'; import Button from '../base/Button'; +import Link from '../base/Link'; import imgLight from '../../../static/themes/light.png'; import imgDark from '../../../static/themes/dark.png'; import imgDefault from '../../../static/themes/default.png'; +import imgSolarizedLight from '../../../static/themes/solarized-light.png'; +import imgSolarizedDark from '../../../static/themes/solarized-dark.png'; +import imgSolarized from '../../../static/themes/solarized.png'; +import imgRailscasts from '../../../static/themes/railscasts.png'; +import imgPurple from '../../../static/themes/purple.png'; +import imgMaterial from '../../../static/themes/material.png'; +import * as session from '../../../sync/session'; -const THEMES = [[ +const THEMES_PER_ROW = 3; +const THEMES = [ {key: 'default', name: 'Insomnia', img: imgDefault}, {key: 'light', name: 'Simple Light', img: imgLight}, - {key: 'dark', name: 'Simple Dark', img: imgDark}, -]]; + {key: 'dark', name: 'Simple Dark', img: imgDark, paid: true}, + {key: 'purple', name: 'Purple', img: imgPurple, paid: true}, + {key: 'material', name: 'Material', img: imgMaterial, paid: true}, + {key: 'solarized', name: 'Solarized', img: imgSolarized, paid: true}, + {key: 'solarized-light', name: 'Solarized Light', img: imgSolarizedLight, paid: true}, + {key: 'solarized-dark', name: 'Solarized Dark', img: imgSolarizedDark, paid: true}, + {key: 'railscasts', name: 'Railscasts', img: imgRailscasts, paid: true}, +]; class SettingsTheme extends Component { - render () { + state = { + isPremium: localStorage.getItem('settings.theme.isPremium') || false, + }; + + async componentDidMount () { + // NOTE: This is kind of sketchy because we're relying on our parent (tab view) + // to remove->add us every time our tab is shown. If it didn't, we would need to + // also hook into componentWillUpdate somehow to refresh more often. + + if (!session.isLoggedIn()) { + this.setState({isPremium: false}); + return; + } + + const {isPremium} = await session.whoami(); + if (this.state.isPremium !== isPremium) { + this.setState({isPremium}); + localStorage.setItem('settings.theme.isPremium', isPremium); + } + } + + renderTheme = theme => { const {handleChangeTheme, activeTheme} = this.props; + const {isPremium} = this.state; + const isActive = activeTheme === theme.key; + const disabled = theme.paid && !isPremium; + return ( -
    - {THEMES.map(row => { - return ( -
    - {row.map(theme => ( -
    -

    - {theme.name} -

    - - {theme.key === activeTheme ? ( -

    - Active -

    - ) : null} -
    - ))} -
    - ); - })} +
    +

    + {theme.name} + {" "} + {isActive ? (Active) : null} +

    + {disabled ? ( + + {theme.name} + + ) : ( + + )} +
    + ) + }; + + renderThemeRows (themes) { + const rows = []; + let row = []; + + for (const theme of themes) { + row.push(theme); + if (row.length === THEMES_PER_ROW) { + rows.push(row); + row = []; + } + } + + // Push the last row if it wasn't finished + if (row.length) { + rows.push(row); + } + + return rows.map((row, i) => ( +
    + {row.map(this.renderTheme)} +
    + )); + }; + + render () { + return ( +
    + {this.renderThemeRows(THEMES)}
    ) } diff --git a/app/ui/components/sidebar/SidebarRequestRow.js b/app/ui/components/sidebar/SidebarRequestRow.js index d0b83abcdb..9ce81bc137 100644 --- a/app/ui/components/sidebar/SidebarRequestRow.js +++ b/app/ui/components/sidebar/SidebarRequestRow.js @@ -75,7 +75,7 @@ class SidebarRequestRow extends PureComponent {
  • @@ -83,7 +83,7 @@ class SidebarRequestRow extends PureComponent { } else { node = (
  • -
    +