Skip to content

Commit

Permalink
feat(App): Improved spell checker & context menu
Browse files Browse the repository at this point in the history
  • Loading branch information
adlk committed Nov 30, 2018
1 parent 8b64855 commit 3d87c0e
Show file tree
Hide file tree
Showing 21 changed files with 1,188 additions and 353 deletions.
821 changes: 658 additions & 163 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,22 @@
"classnames": "^2.2.5",
"debug-electron": "^0.0.4",
"du": "^0.1.0",
"electron-dl": "1.12.0",
"electron-fetch": "1.3.0",
"electron-hunspell": "0.1.1",
"electron-react-titlebar": "0.8.1",
"electron-spellchecker": "^1.1.2",
"electron-updater": "^4.0.4",
"electron-window-state": "^4.1.0",
"fs-extra": "7.0.1",
"gulp-cli": "1.2.2",
"hunspell-dict-downloader": "1.0.0",
"ini": "^1.3.4",
"jshashes": "^1.0.6",
"jsonwebtoken": "^7.4.1",
"keymaster": "^1.6.2",
"lodash": "^4.17.4",
"mdi": "^1.9.33",
"mime-types": "2.1.21",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"mobx": "^3.1.0",
Expand Down
21 changes: 12 additions & 9 deletions src/components/settings/settings/EditSettingsForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ export default @observer class EditSettingsForm extends Component {
{/* Language */}
<h2 id="language">{intl.formatMessage(messages.headlineLanguage)}</h2>
<Select field={form.$('locale')} showLabel={false} />
<PremiumFeatureContainer
condition={isSpellcheckerPremiumFeature}
>
<div>
<Toggle
field={form.$('enableSpellchecking')}
/>
{form.$('enableSpellchecking').value && (
<Select field={form.$('spellcheckerLanguage')} />
)}
</div>
</PremiumFeatureContainer>
<a
href={FRANZ_TRANSLATION}
target="_blank"
Expand All @@ -178,17 +190,8 @@ export default @observer class EditSettingsForm extends Component {

{/* Advanced */}
<h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2>
<PremiumFeatureContainer
condition={isSpellcheckerPremiumFeature}
>
<Toggle
field={form.$('enableSpellchecking')}
disabled
/>
</PremiumFeatureContainer>
<Toggle field={form.$('enableGPUAcceleration')} />
<p className="settings__help">{intl.formatMessage(messages.enableGPUAccelerationInfo)}</p>
{/* <Select field={form.$('spellcheckingLanguage')} /> */}
<div className="settings__settings-group">
<h3>
{intl.formatMessage(messages.subheadlineCache)}
Expand Down
3 changes: 3 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const DEFAULT_APP_SETTINGS = {
showDisabledServices: true,
showMessageBadgeWhenMuted: true,
enableSpellchecking: true,
spellcheckerLanguage: 'en-us',
darkMode: false,
locale: '',
fallbackLocale: 'en-US',
Expand All @@ -35,3 +36,5 @@ export const FILE_SYSTEM_SETTINGS_TYPES = [
];

export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config');

export const DICTIONARY_PATH = path.join(app.getPath('userData'), 'dicts');
21 changes: 18 additions & 3 deletions src/containers/settings/EditSettingsScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AppStore from '../../stores/AppStore';
import SettingsStore from '../../stores/SettingsStore';
import UserStore from '../../stores/UserStore';
import Form from '../../lib/Form';
import { APP_LOCALES } from '../../i18n/languages';
import { APP_LOCALES, SPELLCHECKER_LOCALES } from '../../i18n/languages';
import { gaPage } from '../../lib/analytics';
import { DEFAULT_APP_SETTINGS } from '../../config';
import { config as spellcheckerConfig } from '../../features/spellchecker';
Expand Down Expand Up @@ -60,8 +60,8 @@ const messages = defineMessages({
id: 'settings.app.form.enableGPUAcceleration',
defaultMessage: '!!!Enable GPU Acceleration',
},
spellcheckingLanguage: {
id: 'settings.app.form.spellcheckingLanguage',
spellcheckerLanguage: {
id: 'settings.app.form.spellcheckerLanguage',
defaultMessage: '!!!Language for spell checking',
},
beta: {
Expand Down Expand Up @@ -98,6 +98,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
darkMode: settingsData.darkMode,
showMessageBadgeWhenMuted: settingsData.showMessageBadgeWhenMuted,
enableSpellchecking: settingsData.enableSpellchecking,
spellcheckerLanguage: settingsData.spellcheckerLanguage,
beta: settingsData.beta, // we need this info in the main process as well
locale: settingsData.locale, // we need this info in the main process as well
},
Expand All @@ -123,6 +124,14 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
});
});

const spellcheckingLanguages = [];
Object.keys(SPELLCHECKER_LOCALES).sort(Intl.Collator().compare).forEach((key) => {
spellcheckingLanguages.push({
value: key,
label: SPELLCHECKER_LOCALES[key],
});
});

const config = {
fields: {
autoLaunchOnStart: {
Expand Down Expand Up @@ -165,6 +174,12 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : settings.all.app.enableSpellchecking,
default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : DEFAULT_APP_SETTINGS.enableSpellchecking,
},
spellcheckerLanguage: {
label: intl.formatMessage(messages.spellcheckerLanguage),
value: settings.all.app.spellcheckerLanguage,
options: spellcheckingLanguages,
default: DEFAULT_APP_SETTINGS.spellcheckerLanguage,
},
darkMode: {
label: intl.formatMessage(messages.darkMode),
value: settings.all.app.darkMode,
Expand Down
43 changes: 43 additions & 0 deletions src/electron/ipc-api/download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ipcMain, dialog } from 'electron';
import { download } from 'electron-dl';
import mime from 'mime-types';
import fs from 'fs-extra';

const debug = require('debug')('Franz:ipcApi:download');

function decodeBase64Image(dataString) {
const matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);

if (matches.length !== 3) {
return new Error('Invalid input string');
}

return new Buffer(matches[2], 'base64');
}

export default (params) => {
ipcMain.on('download-file', async (event, { url, content, fileOptions = {} }) => {
try {
if (!content) {
const dl = await download(params.mainWindow, url, {
saveAs: true,
});
debug('File saved to', dl.getSavePath());
} else {
const extension = mime.extension(fileOptions.mime);
const filename = `${fileOptions.name}.${extension}`;

dialog.showSaveDialog(params.mainWindow, {
defaultPath: filename,
}, (name) => {
const binaryImage = decodeBase64Image(content);
fs.writeFileSync(name, binaryImage, 'binary');

debug('File blob saved to', name);
});
}
} catch (e) {
console.error(e);
}
});
};
2 changes: 2 additions & 0 deletions src/electron/ipc-api/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import autoUpdate from './autoUpdate';
import settings from './settings';
import appIndicator from './appIndicator';
import download from './download';

export default (params) => {
settings(params);
autoUpdate(params);
appIndicator(params);
download(params);
};
28 changes: 13 additions & 15 deletions src/features/spellchecker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,24 @@ export default function init(stores) {
reaction(
() => stores.features.features.isSpellcheckerPremiumFeature,
(enabled, r) => {
if (enabled) {
debug('Initializing `spellchecker` feature');
debug('Initializing `spellchecker` feature');

// Dispose the reaction to run this only once
r.dispose();
// Dispose the reaction to run this only once
r.dispose();

const { isSpellcheckerPremiumFeature } = stores.features.features;
const { isSpellcheckerPremiumFeature } = stores.features.features;

config.isPremiumFeature = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_IS_PREMIUM_FEATURE;
config.isPremiumFeature = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_IS_PREMIUM_FEATURE;

autorun(() => {
if (!stores.user.data.isPremium && config.isPremiumFeature) {
debug('Override settings.spellcheckerEnabled flag to false');
autorun(() => {
if (!stores.user.data.isPremium && config.isPremiumFeature) {
debug('Override settings.spellcheckerEnabled flag to false');

Object.assign(stores.settings.all.app, {
enableSpellchecker: false,
});
}
});
}
Object.assign(stores.settings.all.app, {
enableSpellchecker: false,
});
}
});
},
);
}
Expand Down
26 changes: 0 additions & 26 deletions src/features/spellchecker/styles.js

This file was deleted.

27 changes: 27 additions & 0 deletions src/helpers/i18n-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export function getLocale({ locale, locales, defaultLocale, fallbackLocale }) {
let localeStr = locale;
if (locales[locale] === undefined) {
let localeFuzzy;
Object.keys(locales).forEach((localStr) => {
if (locales && Object.hasOwnProperty.call(locales, localStr)) {
if (locale.substring(0, 2) === localStr.substring(0, 2)) {
localeFuzzy = localStr;
}
}
});

if (localeFuzzy !== undefined) {
localeStr = localeFuzzy;
}
}

if (locales[localeStr] === undefined) {
localeStr = defaultLocale;
}

if (!localeStr) {
localeStr = fallbackLocale;
}

return localeStr;
}
80 changes: 39 additions & 41 deletions src/i18n/languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,43 @@ export const APP_LOCALES = {
es: 'Español',
};

export default APP_LOCALES;
// Hunspell compatible keys
export const SPELLCHECKER_LOCALES = {
'bg-bg': 'български език',
'ca-es': 'Català',
'cs-cz': 'Čeština',
'da-dk': 'Dansk',
'de-de': 'Deutsch',
'el-gr': 'λληνικά (Greek)',
'en-us': 'English',
'es-es': 'Español',
'et-ee': 'Estonian',
'fa-ir': 'فارسی (Persian)',
'fo-fo': 'Faroese',
'fr-fr': 'Français',
'he-il': 'עברית (Hebrew)',
'hr-hr': 'Hrvatski jezik',
'hu-hu': 'Magyar',
'it-it': 'Italiano',
ko: 'Korean',
'lt-lt': 'Lietuvių kalba',
'lv-lv': 'Latviešu valoda',
'nb-no': 'Norsk bokmål',
'nl-nl': 'Nederlands',
'pl-pl': 'Język polski',

This comment has been minimized.

Copy link
@zajacp

zajacp Dec 2, 2018

should be "Polski"

'pt-br': 'Português (Brazil)',
'pt-pt': 'Português',
'ro-ro': 'Limba română',
'ru-ru': 'Русский (Russian)',
'sk-sk': 'Slovenčina',
'sl-si': 'Slovenski jezik',
sr: 'Српски језик (Serbian)',
'sv-se': 'Svenska',
'ta-in': 'தமிழ் (Tamil)',
'tg-tg': 'Тоҷикӣ (Tajik)',
tr: 'Türkçe',
'uk-ua': 'Українська (Ukrainian)',
vi: 'Tiếng Việt',
};

// export const SPELLCHECKER_LOCALES = {
// af: 'Afrikaans',
// sq: 'Albanian',
// ar: 'Arabic',
// bg: 'Bulgarian',
// zh: 'Chinese',
// hr: 'Croatian',
// cs: 'Czech',
// da: 'Danish',
// nl: 'Dutch',
// en: 'English',
// 'en-AU': 'English (AU)',
// 'en-CA': 'English (CA)',
// 'en-GB': 'English (GB)',
// fi: 'Finnish',
// fr: 'French',
// ka: 'Georgian',
// de: 'German',
// el: 'Greek, Modern',
// hi: 'Hindi',
// hu: 'Hungarian',
// id: 'Indonesian',
// it: 'Italian',
// ja: 'Japanese',
// jv: 'Javanese',
// ko: 'Korean',
// lt: 'Lithuanian',
// lv: 'Latvian',
// ms: 'Malay',
// no: 'Norwegian',
// pl: 'Polish',
// pt: 'Portuguese',
// ro: 'Romanian, Moldavian, Moldovan',
// ru: 'Russian',
// sk: 'Slovak',
// es: 'Spanish',
// sv: 'Swedish',
// uk: 'Ukrainian',
// vi: 'Vietnamese',
// };
export default APP_LOCALES;
1 change: 1 addition & 0 deletions src/i18n/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
"settings.app.form.runInBackground": "Keep Franz in background when closing the window",
"settings.app.form.language": "Language",
"settings.app.form.enableSpellchecking": "Enable spell checking",
"settings.app.form.spellcheckerLanguage": "Spell checking language",
"settings.app.form.enableGPUAcceleration": "Enable GPU Acceleration",
"settings.app.form.showDisabledServices": "Display disabled services tabs",
"settings.app.form.showMessagesBadgesWhenMuted": "Show unread message badge when notifications are disabled",
Expand Down
Loading

0 comments on commit 3d87c0e

Please sign in to comment.