mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-30 10:36:35 +02:00
Merge branch 'tidy_config'
This commit is contained in:
commit
5db7502fe4
@ -333,7 +333,6 @@ class Application extends BaseApplication {
|
||||
|
||||
const importItems = [];
|
||||
const exportItems = [];
|
||||
const preferencesItems = [];
|
||||
const toolsItemsFirst = [];
|
||||
const templateItems = [];
|
||||
const ioService = new InteropService();
|
||||
@ -480,33 +479,6 @@ class Application extends BaseApplication {
|
||||
},
|
||||
};
|
||||
|
||||
preferencesItems.push({
|
||||
label: _('General Options'),
|
||||
accelerator: 'CommandOrControl+,',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
});
|
||||
},
|
||||
}, {
|
||||
label: _('Encryption options'),
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'EncryptionConfig',
|
||||
});
|
||||
},
|
||||
}, {
|
||||
label: _('Web clipper options'),
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'ClipperConfig',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
toolsItemsFirst.push(syncStatusItem, {
|
||||
type: 'separator',
|
||||
screens: ['Main'],
|
||||
@ -563,7 +535,17 @@ class Application extends BaseApplication {
|
||||
},
|
||||
});
|
||||
|
||||
const toolsItems = toolsItemsFirst.concat(preferencesItems);
|
||||
const toolsItems = toolsItemsFirst.push({
|
||||
label: _('Options'),
|
||||
visible: !shim.isMac(),
|
||||
accelerator: 'CommandOrControl+,',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function _checkForUpdates(ctx) {
|
||||
bridge().checkForUpdates(false, bridge().window(), ctx.checkForUpdateLoggerPath(), { includePreReleases: Setting.value('autoUpdate.includePreReleases') });
|
||||
@ -608,7 +590,13 @@ class Application extends BaseApplication {
|
||||
}, {
|
||||
label: _('Preferences...'),
|
||||
visible: shim.isMac() ? true : false,
|
||||
submenu: preferencesItems,
|
||||
accelerator: 'CommandOrControl+,',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Config',
|
||||
});
|
||||
},
|
||||
}, {
|
||||
label: _('Check for updates...'),
|
||||
visible: shim.isMac() ? true : false,
|
||||
|
@ -122,6 +122,10 @@ class Bridge {
|
||||
checkForUpdates(inBackground, window, logFilePath, options);
|
||||
}
|
||||
|
||||
buildDir() {
|
||||
return this.electronApp().buildDir();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let bridge_ = null;
|
||||
|
2
ElectronClient/app/build/images/chrome-logo.svg
Normal file
2
ElectronClient/app/build/images/chrome-logo.svg
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 433.43759 401.99866" height="304.543276757" width="328.360557044" xml:space="preserve" id="svg10" version="1.1"><metadata id="metadata16"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><defs id="defs14"><clipPath id="clipPath26" clipPathUnits="userSpaceOnUse"><path id="path24" d="M 0,792 H 612 V 0 H 0 Z"/></clipPath><clipPath id="clipPath44" clipPathUnits="userSpaceOnUse"><path id="path42" d="M 143.461,245.334 H 468.539 V 420.666 H 143.461 Z"/></clipPath></defs><g transform="matrix(1.3333333,0,0,-1.3333333,-191.2812,729.11065)" id="g18"><g id="g91"><g id="g20"><g id="g22" clip-path="url(#clipPath26)"><g id="g28" transform="translate(143.4609,254.334)"><path d="m 0,0 c 0,-4.971 4.029,-9 9,-9 h 307.078 c 4.971,0 9,4.029 9,9 v 157.331 c 0,4.971 -4.029,9 -9,9 H 9 c -4.971,0 -9,-4.029 -9,-9 z" style="fill:#efeff0;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path30"/></g><path d="m 354.157,522.753 h -96.818 v 24.08 h 96.818 z" style="fill:#abadad;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path32"/><g id="g34" transform="translate(468.5391,372.2559)"><path d="m 0,0 h -325.078 v 126.417 h 90.805 l -0.003,24.08 23.076,24.08 0.008,-48.16 h 96.807 l 0.006,48.16 24.079,-24.08 -0.006,-24.08 H 0 Z" style="fill:#e3e4e5;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path36"/></g></g></g><g id="g38"><g id="g40" clip-path="url(#clipPath44)"><g id="g46" transform="translate(305.6372,413.5986)"><path d="M 0,0 C 0,0 82.026,3.692 125.5,-78.741 H -6.973 c 0,0 -25.017,0.822 -46.346,-29.53 -6.149,-12.716 -12.71,-25.841 -5.329,-51.675 -10.664,18.042 -56.599,98.018 -56.599,98.018 0,0 32.402,58.649 115.247,61.928" style="fill:#e14c40;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path48"/></g><g id="g50" transform="translate(426.8643,204.3018)"><path d="m 0,0 c 0,0 -37.825,-72.871 -130.954,-69.291 11.49,19.885 66.251,114.714 66.251,114.714 0,0 13.222,21.252 -2.387,54.897 -7.936,11.687 -16.02,23.933 -42.087,30.464 C -88.213,130.99 4.009,130.77 4.009,130.77 4.009,130.77 38.589,73.38 0,0" style="fill:#ffd24d;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path52"/></g><g id="g54" transform="translate(184.9966,203.7461)"><path d="M 0,0 C 0,0 -44.197,69.203 5.476,148.06 16.955,128.166 71.687,33.318 71.687,33.318 c 0,0 11.793,-22.075 48.739,-25.381 14.087,1.029 28.732,1.905 47.42,21.21 -10.3,-18.253 -56.609,-98.012 -56.609,-98.012 0,0 -66.989,-1.249 -111.237,68.865" style="fill:#00aa60;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path56"/></g><g id="g58" transform="translate(243.23,273.1113)"><path d="m 0,0 c 0,34.273 27.786,62.063 62.066,62.063 34.278,0 62.061,-27.79 62.061,-62.063 0,-34.283 -27.783,-62.069 -62.061,-62.069 C 27.786,-62.069 0,-34.283 0,0" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path60"/></g><g id="g62" transform="translate(256.6279,273.1113)"><path d="M 0,0 C 0,26.875 21.79,48.665 48.668,48.665 75.539,48.665 97.332,26.875 97.332,0 97.332,-26.879 75.539,-48.668 48.668,-48.668 21.79,-48.668 0,-26.879 0,0" style="fill:#577fc0;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path64"/></g><g id="g66" transform="translate(305.6357,413.5986)"><path d="m 0,0 c 0,0 54.153,2.437 97.777,-40.864 -0.717,0 -148.959,-0.477 -196.584,-0.477 C -81.582,-24.098 -49.965,-1.979 0,0" style="fill:#d6483e;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path68"/></g></g></g></g></g></svg>
|
After Width: | Height: | Size: 3.7 KiB |
1
ElectronClient/app/build/images/firefox-logo.svg
Normal file
1
ElectronClient/app/build/images/firefox-logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 16 KiB |
File diff suppressed because one or more lines are too long
44
ElectronClient/app/gui/ConfigMenuBar.jsx
Normal file
44
ElectronClient/app/gui/ConfigMenuBar.jsx
Normal file
@ -0,0 +1,44 @@
|
||||
const React = require('react');
|
||||
const styleSelector = require('./style/ConfigMenuBar');
|
||||
const Setting = require('lib/models/Setting');
|
||||
|
||||
function ConfigMenuBarButton(props) {
|
||||
const style = styleSelector(null, props);
|
||||
|
||||
const iconStyle = props.selected ? style.buttonIconSelected : style.buttonIcon;
|
||||
const labelStyle = props.selected ? style.buttonLabelSelected : style.buttonLabel;
|
||||
|
||||
return (
|
||||
<button style={style.button} onClick={props.onClick}>
|
||||
<i style={iconStyle} className={'fa ' + props.iconName}></i>
|
||||
<span style={labelStyle}>{props.label}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function ConfigMenuBar(props) {
|
||||
const buttons = [];
|
||||
|
||||
const style = styleSelector(null, props);
|
||||
|
||||
for (const section of props.sections) {
|
||||
buttons.push(<ConfigMenuBarButton
|
||||
selected={props.selection === section.name}
|
||||
theme={props.theme}
|
||||
key={section.name}
|
||||
iconName={Setting.sectionNameToIcon(section.name)}
|
||||
label={Setting.sectionNameToLabel(section.name)}
|
||||
onClick={() => { props.onSelectionChange({ section: section });}}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={style.root} className="config-menu-bar">
|
||||
<div style={style.barButtons}>
|
||||
{buttons}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ConfigMenuBar;
|
@ -7,6 +7,9 @@ const pathUtils = require('lib/path-utils.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const shared = require('lib/components/shared/config-shared.js');
|
||||
const ConfigMenuBar = require('./ConfigMenuBar.min.js');
|
||||
const { EncryptionConfigScreen } = require('./EncryptionConfigScreen.min');
|
||||
const { ClipperConfigScreen } = require('./ClipperConfigScreen.min');
|
||||
|
||||
class ConfigScreenComponent extends React.Component {
|
||||
constructor() {
|
||||
@ -14,6 +17,9 @@ class ConfigScreenComponent extends React.Component {
|
||||
|
||||
shared.init(this);
|
||||
|
||||
this.state.selectedSectionName = 'general';
|
||||
this.state.screenName = '';
|
||||
|
||||
this.checkSyncConfig_ = async () => {
|
||||
await shared.checkSyncConfig(this, this.state.settings);
|
||||
};
|
||||
@ -21,12 +27,57 @@ class ConfigScreenComponent extends React.Component {
|
||||
this.rowStyle_ = {
|
||||
marginBottom: 10,
|
||||
};
|
||||
|
||||
this.configMenuBar_selectionChange = this.configMenuBar_selectionChange.bind(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.setState({ settings: this.props.settings });
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.defaultSection) {
|
||||
this.setState({ selectedSectionName: this.props.defaultSection }, () => {
|
||||
this.switchSection(this.props.defaultSection);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sectionByName(name) {
|
||||
const sections = shared.settingsSections({ device: 'desktop', settings: this.state.settings });
|
||||
for (const section of sections) {
|
||||
if (section.name === name) return section;
|
||||
}
|
||||
|
||||
throw new Error('Invalid section name: ' + name);
|
||||
}
|
||||
|
||||
screenFromName(screenName) {
|
||||
if (screenName === 'encryption') return <EncryptionConfigScreen theme={this.props.theme}/>;
|
||||
if (screenName === 'server') return <ClipperConfigScreen theme={this.props.theme}/>;
|
||||
|
||||
throw new Error('Invalid screen name: ' + screenName);
|
||||
}
|
||||
|
||||
switchSection(name) {
|
||||
const section = this.sectionByName(name);
|
||||
let screenName = '';
|
||||
if (section.isScreen) {
|
||||
screenName = section.name;
|
||||
|
||||
if (this.hasChanges()) {
|
||||
const ok = confirm(_('This will open a new screen. Save your current changes?'));
|
||||
if (ok) shared.saveSettings(this);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ selectedSectionName: section.name, screenName: screenName });
|
||||
}
|
||||
|
||||
configMenuBar_selectionChange(event) {
|
||||
this.switchSection(event.section.name);
|
||||
}
|
||||
|
||||
keyValueToArray(kv) {
|
||||
let output = [];
|
||||
for (let k in kv) {
|
||||
@ -40,7 +91,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
return output;
|
||||
}
|
||||
|
||||
sectionToComponent(key, section, settings) {
|
||||
sectionToComponent(key, section, settings, selected) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const settingComps = [];
|
||||
|
||||
@ -52,15 +103,11 @@ class ConfigScreenComponent extends React.Component {
|
||||
}
|
||||
|
||||
const sectionStyle = {
|
||||
marginTop: 20,
|
||||
marginBottom: 20,
|
||||
};
|
||||
|
||||
const headerStyle = Object.assign({}, theme.headerStyle, {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
borderBottomStyle: 'solid',
|
||||
paddingBottom: '.4em',
|
||||
});
|
||||
if (!selected) sectionStyle.display = 'none';
|
||||
|
||||
if (section.name === 'general') {
|
||||
sectionStyle.borderTopWidth = 0;
|
||||
@ -94,7 +141,6 @@ class ConfigScreenComponent extends React.Component {
|
||||
|
||||
return (
|
||||
<div key={key} style={sectionStyle}>
|
||||
<h2 style={headerStyle}>{Setting.sectionNameToLabel(section.name)}</h2>
|
||||
{noteComp}
|
||||
<div>{settingComps}</div>
|
||||
</div>
|
||||
@ -123,6 +169,10 @@ class ConfigScreenComponent extends React.Component {
|
||||
opacity: 0,
|
||||
});
|
||||
|
||||
const checkboxLabelStyle = Object.assign({}, labelStyle, {
|
||||
marginLeft: 8,
|
||||
});
|
||||
|
||||
const controlStyle = {
|
||||
display: 'inline-block',
|
||||
color: theme.color,
|
||||
@ -136,6 +186,13 @@ class ConfigScreenComponent extends React.Component {
|
||||
maxWidth: '70em',
|
||||
});
|
||||
|
||||
const textInputBaseStyle = Object.assign({}, controlStyle, {
|
||||
border: '1px solid',
|
||||
padding: '4px 6px',
|
||||
borderColor: theme.dividerColor,
|
||||
borderRadius: 4,
|
||||
});
|
||||
|
||||
const updateSettingValue = (key, value) => {
|
||||
// console.info(key + ' = ' + value);
|
||||
return shared.updateSettingValue(this, key, value);
|
||||
@ -161,6 +218,8 @@ class ConfigScreenComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
const selectStyle = Object.assign({}, controlStyle, { height: 22, borderColor: theme.dividerColor });
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
<div style={labelStyle}>
|
||||
@ -168,7 +227,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
</div>
|
||||
<select
|
||||
value={value}
|
||||
style={controlStyle}
|
||||
style={selectStyle}
|
||||
onChange={event => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
}}
|
||||
@ -201,7 +260,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
onClick={event => {
|
||||
onCheckboxClick(event);
|
||||
}}
|
||||
style={labelStyle}
|
||||
style={checkboxLabelStyle}
|
||||
htmlFor={'setting_checkbox_' + key}
|
||||
>
|
||||
{md.label()}
|
||||
@ -211,10 +270,9 @@ class ConfigScreenComponent extends React.Component {
|
||||
</div>
|
||||
);
|
||||
} else if (md.type === Setting.TYPE_STRING) {
|
||||
const inputStyle = Object.assign({}, controlStyle, {
|
||||
const inputStyle = Object.assign({}, textInputBaseStyle, {
|
||||
width: '50%',
|
||||
minWidth: '20em',
|
||||
border: '1px solid',
|
||||
});
|
||||
const inputType = md.secure === true ? 'password' : 'text';
|
||||
|
||||
@ -279,7 +337,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
}}
|
||||
value={cmd[0]}
|
||||
/>
|
||||
<button onClick={browseButtonClick} style={Object.assign({}, theme.buttonStyle, { marginLeft: 5, minHeight: 20, height: 20 })}>
|
||||
<button onClick={browseButtonClick} style={Object.assign({}, theme.buttonStyle, { marginLeft: 5 })}>
|
||||
{_('Browse...')}
|
||||
</button>
|
||||
</div>
|
||||
@ -334,6 +392,8 @@ class ConfigScreenComponent extends React.Component {
|
||||
const label = [md.label()];
|
||||
if (md.unitLabel) label.push('(' + md.unitLabel() + ')');
|
||||
|
||||
const inputStyle = Object.assign({}, textInputBaseStyle);
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
<div style={labelStyle}>
|
||||
@ -341,7 +401,7 @@ class ConfigScreenComponent extends React.Component {
|
||||
</div>
|
||||
<input
|
||||
type="number"
|
||||
style={controlStyle}
|
||||
style={inputStyle}
|
||||
value={this.state.settings[key]}
|
||||
onChange={event => {
|
||||
onNumChange(event);
|
||||
@ -373,6 +433,10 @@ class ConfigScreenComponent extends React.Component {
|
||||
this.props.dispatch({ type: 'NAV_BACK' });
|
||||
}
|
||||
|
||||
hasChanges() {
|
||||
return !!this.state.changedSettingKeys.length;
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
@ -390,9 +454,9 @@ class ConfigScreenComponent extends React.Component {
|
||||
|
||||
let settings = this.state.settings;
|
||||
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0 });
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0, display: 'flex', flex: 1 });
|
||||
|
||||
const hasChanges = !!this.state.changedSettingKeys.length;
|
||||
const hasChanges = this.hasChanges();
|
||||
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, {
|
||||
display: 'inline-block',
|
||||
@ -403,19 +467,33 @@ class ConfigScreenComponent extends React.Component {
|
||||
opacity: hasChanges ? 1 : theme.disabledOpacity,
|
||||
});
|
||||
|
||||
const settingComps = shared.settingsToComponents2(this, 'desktop', settings);
|
||||
const settingComps = shared.settingsToComponents2(this, 'desktop', settings, this.state.selectedSectionName);
|
||||
|
||||
const buttonBarStyle = {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomStyle: 'solid',
|
||||
borderBottomColor: theme.dividerColor,
|
||||
padding: 10,
|
||||
borderTopWidth: 1,
|
||||
borderTopStyle: 'solid',
|
||||
borderTopColor: theme.dividerColor,
|
||||
};
|
||||
|
||||
const screenComp = this.state.screenName ? <div style={{overflow: 'scroll', flex:1}}>{this.screenFromName(this.state.screenName)}</div> : null;
|
||||
|
||||
if (screenComp) containerStyle.display = 'none';
|
||||
|
||||
const sections = shared.settingsSections({ device: 'desktop', settings });
|
||||
|
||||
return (
|
||||
<div style={style}>
|
||||
<ConfigMenuBar
|
||||
selection={this.state.selectedSectionName}
|
||||
onSelectionChange={this.configMenuBar_selectionChange}
|
||||
sections={sections}
|
||||
theme={this.props.theme}
|
||||
/>
|
||||
{screenComp}
|
||||
<div style={containerStyle}>{settingComps}</div>
|
||||
<div style={buttonBarStyle}>
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -424,28 +502,15 @@ class ConfigScreenComponent extends React.Component {
|
||||
style={buttonStyle}
|
||||
>
|
||||
<i style={theme.buttonIconStyle} className={'fa fa-chevron-left'}></i>
|
||||
{_('Cancel')}
|
||||
</button>
|
||||
<button
|
||||
disabled={!hasChanges}
|
||||
onClick={() => {
|
||||
this.onSaveClick();
|
||||
}}
|
||||
style={buttonStyleApprove}
|
||||
>
|
||||
{_('OK')}
|
||||
</button>
|
||||
<button
|
||||
disabled={!hasChanges}
|
||||
onClick={() => {
|
||||
this.onApplyClick();
|
||||
}}
|
||||
style={buttonStyleApprove}
|
||||
>
|
||||
{_('Apply')}
|
||||
{hasChanges && !screenComp ? _('Cancel') : _('Back')}
|
||||
</button>
|
||||
{ !screenComp && (
|
||||
<div>
|
||||
<button disabled={!hasChanges} onClick={() => { this.onSaveClick(); }} style={buttonStyleApprove}>{_('OK')}</button>
|
||||
<button disabled={!hasChanges} onClick={() => { this.onApplyClick(); }} style={buttonStyleApprove}>{_('Apply')}</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={containerStyle}>{settingComps}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ const React = require('react');
|
||||
const { connect } = require('react-redux');
|
||||
const Setting = require('lib/models/Setting');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const { Header } = require('./Header.min.js');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
@ -85,17 +84,13 @@ class EncryptionConfigScreenComponent extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const style = this.props.style;
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const masterKeys = this.state.masterKeys;
|
||||
const containerPadding = 10;
|
||||
|
||||
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
|
||||
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, {
|
||||
padding: containerPadding,
|
||||
overflow: 'auto',
|
||||
height: style.height - theme.headerHeight - containerPadding * 2,
|
||||
});
|
||||
|
||||
const mkComps = [];
|
||||
@ -200,7 +195,6 @@ class EncryptionConfigScreenComponent extends React.Component {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header style={headerStyle} />
|
||||
<div style={containerStyle}>
|
||||
{
|
||||
<div style={{ backgroundColor: theme.warningBackgroundColor, paddingLeft: 10, paddingRight: 10, paddingTop: 2, paddingBottom: 2 }}>
|
||||
|
45
ElectronClient/app/gui/ExtensionBadge.jsx
Normal file
45
ElectronClient/app/gui/ExtensionBadge.jsx
Normal file
@ -0,0 +1,45 @@
|
||||
const React = require('react');
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
const styleSelector = require('./style/ExtensionBadge');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
function platformAssets(type) {
|
||||
if (type === 'firefox') {
|
||||
return {
|
||||
logoImage: bridge().buildDir() + '/images/firefox-logo.svg',
|
||||
locationLabel: _('Firefox Extension'),
|
||||
};
|
||||
}
|
||||
|
||||
if (type === 'chrome') {
|
||||
return {
|
||||
logoImage: bridge().buildDir() + '/images/chrome-logo.svg',
|
||||
locationLabel: _('Chrome Web Store'),
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error('Invalid type:' + type);
|
||||
}
|
||||
|
||||
function ExtensionBadge(props) {
|
||||
const style = styleSelector(null, props);
|
||||
const assets = platformAssets(props.type);
|
||||
|
||||
const onClick = () => {
|
||||
bridge().openExternal(props.url);
|
||||
};
|
||||
|
||||
const rootStyle = props.style ? Object.assign({}, style.root, props.style) : style.root;
|
||||
|
||||
return (
|
||||
<a style={rootStyle} onClick={onClick} href="#">
|
||||
<img style={style.logo} src={assets.logoImage}/>
|
||||
<div style={style.labelGroup} >
|
||||
<div>{_('Get it now:')}</div>
|
||||
<div style={style.locationLabel}>{assets.locationLabel}</div>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ExtensionBadge;
|
@ -485,7 +485,10 @@ class MainScreenComponent extends React.Component {
|
||||
const onViewMasterKeysClick = () => {
|
||||
this.props.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'EncryptionConfig',
|
||||
routeName: 'Config',
|
||||
props: {
|
||||
defaultSection: 'encryption',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -17,10 +17,7 @@ class NavigatorComponent extends Component {
|
||||
|
||||
updateWindowTitle(title) {
|
||||
try {
|
||||
if (bridge().window())
|
||||
bridge()
|
||||
.window()
|
||||
.setTitle(title);
|
||||
if (bridge().window()) bridge().window().setTitle(title);
|
||||
} catch (error) {
|
||||
console.warn('updateWindowTitle', error);
|
||||
}
|
||||
|
@ -415,10 +415,10 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (Setting.value('env') === 'dev' && this.webviewRef()) {
|
||||
this.webviewRef().openDevTools();
|
||||
return;
|
||||
}
|
||||
// if (Setting.value('env') === 'dev' && this.webviewRef()) {
|
||||
// this.webviewRef().openDevTools();
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (this.webviewRef() && this.props.noteDevToolsVisible !== this.webviewRef().isDevToolsOpened()) {
|
||||
if (this.props.noteDevToolsVisible) {
|
||||
|
@ -11,8 +11,6 @@ const { DropboxLoginScreen } = require('./DropboxLoginScreen.min.js');
|
||||
const { StatusScreen } = require('./StatusScreen.min.js');
|
||||
const { ImportScreen } = require('./ImportScreen.min.js');
|
||||
const { ConfigScreen } = require('./ConfigScreen.min.js');
|
||||
const { EncryptionConfigScreen } = require('./EncryptionConfigScreen.min.js');
|
||||
const { ClipperConfigScreen } = require('./ClipperConfigScreen.min.js');
|
||||
const { Navigator } = require('./Navigator.min.js');
|
||||
const WelcomeUtils = require('lib/WelcomeUtils');
|
||||
|
||||
@ -89,8 +87,6 @@ class RootComponent extends React.Component {
|
||||
Import: { screen: ImportScreen, title: () => _('Import') },
|
||||
Config: { screen: ConfigScreen, title: () => _('Options') },
|
||||
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },
|
||||
EncryptionConfig: { screen: EncryptionConfigScreen, title: () => _('Encryption Options') },
|
||||
ClipperConfig: { screen: ClipperConfigScreen, title: () => _('Clipper Options') },
|
||||
};
|
||||
|
||||
return <Navigator style={navigatorStyle} screens={screens} />;
|
||||
|
55
ElectronClient/app/gui/style/ConfigMenuBar.js
Normal file
55
ElectronClient/app/gui/style/ConfigMenuBar.js
Normal file
@ -0,0 +1,55 @@
|
||||
const { createSelector } = require('reselect');
|
||||
const { themeStyle } = require('../../theme.js');
|
||||
|
||||
const themeSelector = (state, props) => themeStyle(props.theme);
|
||||
|
||||
const style = createSelector(
|
||||
themeSelector,
|
||||
(theme) => {
|
||||
const output = {
|
||||
button: {
|
||||
fontFamily: theme.fontFamily,
|
||||
minWidth: 52,
|
||||
border: 'none',
|
||||
flexDirection: 'column',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: 9,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
},
|
||||
buttonIcon: {
|
||||
fontSize: 24,
|
||||
color: theme.colorFaded,
|
||||
},
|
||||
buttonLabel: {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
alignItems: 'flex-end',
|
||||
color: theme.colorFaded,
|
||||
},
|
||||
root: {
|
||||
minHeight: 58,
|
||||
display: 'flex',
|
||||
borderBottomWidth: 1,
|
||||
borderBottomStyle: 'solid',
|
||||
borderBottomColor: theme.dividerColor,
|
||||
},
|
||||
barButtons: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
};
|
||||
|
||||
output.buttonIconSelected = Object.assign({}, output.buttonIcon, {
|
||||
color: theme.highlightedColor,
|
||||
});
|
||||
|
||||
output.buttonLabelSelected = Object.assign({}, output.buttonLabel, {
|
||||
color: theme.color,
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = style;
|
49
ElectronClient/app/gui/style/ExtensionBadge.js
Normal file
49
ElectronClient/app/gui/style/ExtensionBadge.js
Normal file
@ -0,0 +1,49 @@
|
||||
const { createSelector } = require('reselect');
|
||||
const { themeStyle } = require('../../theme.js');
|
||||
|
||||
const themeSelector = (state, props) => themeStyle(props.theme);
|
||||
|
||||
const style = createSelector(
|
||||
themeSelector,
|
||||
(theme) => {
|
||||
const output = {
|
||||
root: {
|
||||
width: 220,
|
||||
height: 60,
|
||||
borderRadius: 4,
|
||||
border: '1px solid',
|
||||
borderColor: theme.dividerColor,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
paddingLeft: 14,
|
||||
paddingRight: 14,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 8,
|
||||
boxSizing: 'border-box',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
boxShadow: '0px 1px 1px rgba(0,0,0,0.3)',
|
||||
},
|
||||
logo: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
},
|
||||
labelGroup: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
marginLeft: 14,
|
||||
fontFamily: theme.fontFamily,
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize,
|
||||
},
|
||||
locationLabel: {
|
||||
fontSize: theme.fontSize * 1.2,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
};
|
||||
|
||||
return output;
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = style;
|
5
ElectronClient/app/package-lock.json
generated
5
ElectronClient/app/package-lock.json
generated
@ -5932,6 +5932,11 @@
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
|
||||
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
|
||||
|
@ -24,7 +24,8 @@
|
||||
"appId": "net.cozic.joplin-desktop",
|
||||
"npmRebuild": false,
|
||||
"extraResources": [
|
||||
"build/icons/*"
|
||||
"build/icons/*",
|
||||
"build/images/*"
|
||||
],
|
||||
"win": {
|
||||
"rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp",
|
||||
@ -141,6 +142,7 @@
|
||||
"read-chunk": "^2.1.0",
|
||||
"readability-node": "^0.1.0",
|
||||
"redux": "^3.7.2",
|
||||
"reselect": "^4.0.0",
|
||||
"server-destroy": "^1.0.1",
|
||||
"smalltalk": "^2.5.1",
|
||||
"sprintf-js": "^1.1.1",
|
||||
|
@ -22,6 +22,10 @@ table td, table th {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
@ -140,3 +144,8 @@ table td, table th {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.config-menu-bar button:focus {
|
||||
outline: 0 none;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,11 @@ globalStyle.buttonStyle = {
|
||||
maxWidth: 160,
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 6,
|
||||
boxShadow: '0px 1px 1px rgba(0,0,0,0.3)',
|
||||
fontSize: globalStyle.fontSize,
|
||||
borderRadius: 4,
|
||||
};
|
||||
|
||||
const lightStyle = {
|
||||
@ -140,6 +144,8 @@ const darkStyle = {
|
||||
|
||||
editorTheme: 'twilight',
|
||||
codeThemeCss: 'atom-one-dark-reasonable.css',
|
||||
|
||||
highlightedColor: '#0066C7',
|
||||
};
|
||||
|
||||
// Solarized Styles
|
||||
@ -314,6 +320,11 @@ function addExtraStyles(style) {
|
||||
|
||||
style.dropdownList = Object.assign({}, style.inputStyle);
|
||||
|
||||
// In general the highlighted color, used to highlight text or icons, should be the same as selectedColor2
|
||||
// but some times, depending on the theme, it might be too dark or too light, so it can be
|
||||
// specified directly by the theme too.
|
||||
if (!style.highlightedColor) style.highlightedColor = style.selectedColor2;
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ const Setting = require('lib/models/Setting.js');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { createSelector } = require('reselect');
|
||||
|
||||
const shared = {};
|
||||
|
||||
@ -79,26 +80,51 @@ shared.settingsToComponents = function(comp, device, settings) {
|
||||
return settingComps;
|
||||
};
|
||||
|
||||
shared.settingsToComponents2 = function(comp, device, settings) {
|
||||
const keys = Setting.keys(true, device);
|
||||
const sectionComps = [];
|
||||
const metadatas = [];
|
||||
const deviceSelector = (state) => state.device;
|
||||
const settingsSelector = (state) => state.settings;
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
if (!Setting.isPublic(key)) continue;
|
||||
shared.settingsSections = createSelector(
|
||||
deviceSelector,
|
||||
settingsSelector,
|
||||
(device, settings) => {
|
||||
const keys = Setting.keys(true, device);
|
||||
const metadatas = [];
|
||||
|
||||
const md = Setting.settingMetadata(key);
|
||||
if (md.show && !md.show(settings)) continue;
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
if (!Setting.isPublic(key)) continue;
|
||||
|
||||
metadatas.push(md);
|
||||
const md = Setting.settingMetadata(key);
|
||||
if (md.show && !md.show(settings)) continue;
|
||||
|
||||
metadatas.push(md);
|
||||
}
|
||||
|
||||
const output = Setting.groupMetadatasBySections(metadatas);
|
||||
|
||||
output.push({
|
||||
name: 'encryption',
|
||||
metadatas: [],
|
||||
isScreen: true,
|
||||
});
|
||||
|
||||
output.push({
|
||||
name: 'server',
|
||||
metadatas: [],
|
||||
isScreen: true,
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
);
|
||||
|
||||
const sections = Setting.groupMetadatasBySections(metadatas);
|
||||
shared.settingsToComponents2 = function(comp, device, settings, selectedSectionName = '') {
|
||||
const sectionComps = [];
|
||||
const sections = shared.settingsSections({ device, settings });
|
||||
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
const sectionComp = comp.sectionToComponent(section.name, section, settings);
|
||||
const sectionComp = comp.sectionToComponent(section.name, section, settings, selectedSectionName === section.name);
|
||||
if (!sectionComp) continue;
|
||||
sectionComps.push(sectionComp);
|
||||
}
|
||||
|
@ -811,6 +811,21 @@ class Setting extends BaseModel {
|
||||
if (name === 'plugins') return _('Plugins');
|
||||
if (name === 'application') return _('Application');
|
||||
if (name === 'revisionService') return _('Note History');
|
||||
if (name === 'encryption') return _('Encryption');
|
||||
if (name === 'server') return _('Web Clipper');
|
||||
return name;
|
||||
}
|
||||
|
||||
static sectionNameToIcon(name, platform) {
|
||||
if (name === 'general') return 'fa-sliders';
|
||||
if (name === 'sync') return 'fa-refresh';
|
||||
if (name === 'appearance') return 'fa-pencil';
|
||||
if (name === 'note') return 'fa-file-text-o';
|
||||
if (name === 'plugins') return 'fa-puzzle-piece';
|
||||
if (name === 'application') return 'fa-cog';
|
||||
if (name === 'revisionService') return 'fa-archive-org';
|
||||
if (name === 'encryption') return 'fa-key-modern';
|
||||
if (name === 'server') return 'fa-hand-scissors-o';
|
||||
return name;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user