Skip to content

Commit baf7d60

Browse files
committed
feat(Service): Add option to change spellchecking language by service
1 parent 1d192ca commit baf7d60

File tree

9 files changed

+105
-19
lines changed

9 files changed

+105
-19
lines changed

src/components/settings/services/EditServiceForm.js

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Input from '../../ui/Input';
1414
import Toggle from '../../ui/Toggle';
1515
import Button from '../../ui/Button';
1616
import ImageUpload from '../../ui/ImageUpload';
17+
import Select from '../../ui/Select';
1718

1819
import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer';
1920

@@ -333,6 +334,12 @@ export default @observer class EditServiceForm extends Component {
333334
</div>
334335
</div>
335336

337+
<PremiumFeatureContainer>
338+
<div className="settings__settings-group">
339+
<Select field={form.$('spellcheckerLanguage')} />
340+
</div>
341+
</PremiumFeatureContainer>
342+
336343
{isProxyFeatureEnabled && (
337344
<PremiumFeatureContainer condition={isProxyFeaturePremiumFeature}>
338345
<div className="settings__settings-group">

src/components/ui/Select.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,32 @@ export default @observer class Select extends Component {
99
field: PropTypes.instanceOf(Field).isRequired,
1010
className: PropTypes.string,
1111
showLabel: PropTypes.bool,
12+
disabled: PropTypes.bool,
1213
};
1314

1415
static defaultProps = {
1516
className: null,
1617
focus: false,
1718
showLabel: true,
19+
disabled: false,
1820
};
1921

2022
render() {
2123
const {
2224
field,
2325
className,
2426
showLabel,
27+
disabled,
2528
} = this.props;
2629

30+
console.log('disabled', disabled);
31+
2732
return (
2833
<div
2934
className={classnames({
3035
'franz-form__field': true,
3136
'has-error': field.error,
37+
'is-disabled': disabled,
3238
[`${className}`]: className,
3339
})}
3440
>
@@ -45,12 +51,13 @@ export default @observer class Select extends Component {
4551
id={field.id}
4652
defaultValue={field.value}
4753
className="franz-form__select"
54+
disabled={field.disabled || disabled}
4855
>
4956
{field.options.map(type => (
5057
<option
5158
key={type.value}
5259
value={type.value}
53-
// selected={field.value === }
60+
disabled={type.disabled}
5461
>
5562
{type.label}
5663
</option>

src/containers/settings/EditServiceScreen.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ import { gaPage } from '../../lib/analytics';
1414
import ServiceError from '../../components/settings/services/ServiceError';
1515
import EditServiceForm from '../../components/settings/services/EditServiceForm';
1616
import { required, url, oneRequired } from '../../helpers/validation-helpers';
17+
import { getSelectOptions } from '../../helpers/i18n-helpers';
1718

1819
import { config as proxyFeature } from '../../features/serviceProxy';
1920

21+
import { SPELLCHECKER_LOCALES } from '../../i18n/languages';
22+
2023
const messages = defineMessages({
2124
name: {
2225
id: 'settings.service.form.name',
@@ -74,6 +77,14 @@ const messages = defineMessages({
7477
id: 'settings.service.form.proxy.password',
7578
defaultMessage: '!!!Password',
7679
},
80+
spellcheckerLanguage: {
81+
id: 'settings.service.form.spellcheckerLanguage',
82+
defaultMessage: '!!!Spell checking Language',
83+
},
84+
spellcheckerSystemDefault: {
85+
id: 'settings.service.form.spellcheckerLanguage.default',
86+
defaultMessage: '!!!Use System Default ({default})',
87+
},
7788
});
7889

7990
export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component {
@@ -101,6 +112,11 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
101112
}
102113

103114
prepareForm(recipe, service, proxy) {
115+
const spellcheckerLanguage = getSelectOptions({
116+
locales: SPELLCHECKER_LOCALES,
117+
resetToDefaultText: this.context.intl.formatMessage(messages.spellcheckerSystemDefault, { default: SPELLCHECKER_LOCALES[this.props.stores.settings.app.spellcheckerLanguage] }),
118+
});
119+
104120
const { intl } = this.context;
105121
const config = {
106122
fields: {
@@ -138,7 +154,13 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
138154
isDarkModeEnabled: {
139155
label: intl.formatMessage(messages.enableDarkMode),
140156
value: service.isDarkModeEnabled,
141-
default: this.props.stores.settings.all.app.darkMode,
157+
default: this.props.stores.settings.app.darkMode,
158+
},
159+
spellcheckerLanguage: {
160+
label: intl.formatMessage(messages.spellcheckerLanguage),
161+
value: service.spellcheckerLanguage,
162+
options: spellcheckerLanguage,
163+
disabled: !this.props.stores.settings.app.enableSpellchecking,
142164
},
143165
},
144166
};

src/containers/settings/EditSettingsScreen.js

+6-12
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { gaPage } from '../../lib/analytics';
1212
import { DEFAULT_APP_SETTINGS } from '../../config';
1313
import { config as spellcheckerConfig } from '../../features/spellchecker';
1414

15+
import { getSelectOptions } from '../../helpers/i18n-helpers';
16+
1517

1618
import EditSettingsForm from '../../components/settings/settings/EditSettingsForm';
1719

@@ -116,20 +118,12 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
116118
const { app, settings, user } = this.props.stores;
117119
const { intl } = this.context;
118120

119-
const locales = [];
120-
Object.keys(APP_LOCALES).sort(Intl.Collator().compare).forEach((key) => {
121-
locales.push({
122-
value: key,
123-
label: APP_LOCALES[key],
124-
});
121+
const locales = getSelectOptions({
122+
locales: APP_LOCALES,
125123
});
126124

127-
const spellcheckingLanguages = [];
128-
Object.keys(SPELLCHECKER_LOCALES).sort(Intl.Collator().compare).forEach((key) => {
129-
spellcheckingLanguages.push({
130-
value: key,
131-
label: SPELLCHECKER_LOCALES[key],
132-
});
125+
const spellcheckingLanguages = getSelectOptions({
126+
locales: SPELLCHECKER_LOCALES,
133127
});
134128

135129
const config = {

src/helpers/i18n-helpers.js

+26
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,29 @@ export function getLocale({ locale, locales, defaultLocale, fallbackLocale }) {
2525

2626
return localeStr;
2727
}
28+
29+
export function getSelectOptions({ locales, resetToDefaultText = '' }) {
30+
let options = [];
31+
32+
if (resetToDefaultText) {
33+
options = [
34+
{
35+
value: '',
36+
label: resetToDefaultText,
37+
}, {
38+
value: '───',
39+
label: '───',
40+
disabled: true,
41+
},
42+
];
43+
}
44+
45+
Object.keys(locales).sort(Intl.Collator().compare).forEach((key) => {
46+
options.push({
47+
value: key,
48+
label: locales[key],
49+
});
50+
});
51+
52+
return options;
53+
}

src/models/Service.js

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default class Service {
2929
@observable hasCustomUploadedIcon = false;
3030
@observable hasCrashed = false;
3131
@observable isDarkModeEnabled = false;
32+
@observable spellcheckerLanguage = null;
3233

3334
constructor(data, recipe) {
3435
if (!data) {
@@ -71,6 +72,8 @@ export default class Service {
7172

7273
this.proxy = data.proxy !== undefined ? data.proxy : this.proxy;
7374

75+
this.spellcheckerLanguage = data.spellcheckerLanguage !== undefined ? data.spellcheckerLanguage : this.spellcheckerLanguage;
76+
7477
this.recipe = recipe;
7578

7679
autorun(() => {

src/styles/select.scss

+4
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ $toggle: "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj
2020
min-width: 200px;
2121
padding: 10px;
2222
-webkit-appearance: none;
23+
24+
&[disabled] {
25+
opacity: 0.5;
26+
}
2327
}

src/webview/plugin.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ipcRenderer } from 'electron';
22
import path from 'path';
3+
import { observable } from 'mobx';
34

45
import RecipeWebview from './lib/RecipeWebview';
56

@@ -12,6 +13,8 @@ const debug = require('debug')('Franz:Plugin');
1213

1314
window.franzSettings = {};
1415
let serviceData;
16+
let overrideSpellcheckerLanguage = false;
17+
1518

1619
ipcRenderer.on('initializeRecipe', (e, data) => {
1720
const modulePath = path.join(data.recipe.path, 'webview.js');
@@ -28,6 +31,13 @@ ipcRenderer.on('initializeRecipe', (e, data) => {
2831
injectDarkModeStyle(data.recipe.path);
2932
debug('Add dark theme styles');
3033
}
34+
35+
if (data.spellcheckerLanguage) {
36+
debug('Overriding spellchecker language to', data.spellcheckerLanguage);
37+
switchDict(data.spellcheckerLanguage);
38+
39+
overrideSpellcheckerLanguage = true;
40+
}
3141
} catch (err) {
3242
debug('Recipe initialization failed', err);
3343
}
@@ -42,10 +52,11 @@ ipcRenderer.on('initializeRecipe', (e, data) => {
4252
ipcRenderer.on('settings-update', async (e, data) => {
4353
debug('Settings update received', data);
4454

45-
if (data.enableSpellchecking) {
46-
switchDict(data.spellcheckerLanguage);
47-
} else {
55+
if (!data.enableSpellchecking) {
4856
disableSpellchecker();
57+
} else if (!overrideSpellcheckerLanguage) {
58+
debug('Setting spellchecker language based on app settings to', data.spellcheckerLanguage);
59+
switchDict(data.spellcheckerLanguage);
4960
}
5061

5162
window.franzSettings = data;
@@ -54,6 +65,8 @@ ipcRenderer.on('settings-update', async (e, data) => {
5465
ipcRenderer.on('service-settings-update', (e, data) => {
5566
debug('Service settings update received', data);
5667

68+
serviceData = data;
69+
5770
if (data.isDarkModeEnabled && !isDarkModeStyleInjected()) {
5871
injectDarkModeStyle(serviceData.recipe.path);
5972

@@ -63,6 +76,18 @@ ipcRenderer.on('service-settings-update', (e, data) => {
6376

6477
debug('Disable service dark mode');
6578
}
79+
80+
if (data.spellcheckerLanguage) {
81+
debug('Overriding spellchecker language to', data.spellcheckerLanguage);
82+
switchDict(data.spellcheckerLanguage);
83+
84+
overrideSpellcheckerLanguage = true;
85+
} else {
86+
debug('Going back to default spellchecker language to', window.franzSettings.spellcheckerLanguage);
87+
switchDict(window.franzSettings.spellcheckerLanguage);
88+
89+
overrideSpellcheckerLanguage = false;
90+
}
6691
});
6792

6893
// Needed for current implementation of electrons 'login' event 🤦‍

src/webview/spellchecker.js

-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ let _isEnabled = false;
1313

1414
async function loadDictionary(locale) {
1515
try {
16-
// Replacing app.asar is not beautiful but unforunately necessary
1716
const fileLocation = path.join(DICTIONARY_PATH, `hunspell-dict-${locale}/${locale}`);
18-
console.log(fileLocation, __dirname);
1917
await provider.loadDictionary(locale, `${fileLocation}.dic`, `${fileLocation}.aff`);
2018
} catch (err) {
2119
console.error('Could not load dictionary', err);

0 commit comments

Comments
 (0)