Add support for disabling spell checking (#8604)

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Šimon Brandner 2022-07-28 10:10:04 +02:00 committed by GitHub
parent 8379f5624e
commit bd30b75f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 52 additions and 17 deletions

View File

@ -37,6 +37,7 @@ limitations under the License.
color: $primary-content; color: $primary-content;
margin-top: 10px; /* TODO: Use a spacing variable */ margin-top: 10px; /* TODO: Use a spacing variable */
margin-bottom: 10px; /* TODO: Use a spacing variable */ margin-bottom: 10px; /* TODO: Use a spacing variable */
margin-right: 100px; /* TODO: Use a spacing variable */
&:nth-child(n + 2) { &:nth-child(n + 2) {
margin-top: var(--SettingsTab_heading_nth_child-margin-top); margin-top: var(--SettingsTab_heading_nth_child-margin-top);
@ -50,6 +51,7 @@ limitations under the License.
color: $primary-content; color: $primary-content;
margin-top: $spacing-12; margin-top: $spacing-12;
margin-bottom: 10px; /* TODO: Use a spacing variable */ margin-bottom: 10px; /* TODO: Use a spacing variable */
margin-right: 100px; /* TODO: Use a spacing variable */
} }
.mx_SettingsTab_subsectionText { .mx_SettingsTab_subsectionText {

View File

@ -46,3 +46,7 @@ limitations under the License.
.mx_GeneralUserSettingsTab_warningIcon { .mx_GeneralUserSettingsTab_warningIcon {
vertical-align: middle; vertical-align: middle;
} }
.mx_SettingsTab_section_spellcheck .mx_ToggleSwitch {
float: right;
}

View File

@ -151,7 +151,7 @@ export default abstract class BasePlatform {
* Return true if platform supports multi-language * Return true if platform supports multi-language
* spell-checking, otherwise false. * spell-checking, otherwise false.
*/ */
public supportsMultiLanguageSpellCheck(): boolean { public supportsSpellCheckSettings(): boolean {
return false; return false;
} }
@ -274,6 +274,12 @@ export default abstract class BasePlatform {
public setLanguage(preferredLangs: string[]) {} public setLanguage(preferredLangs: string[]) {}
public setSpellCheckEnabled(enabled: boolean): void {}
public async getSpellCheckEnabled(): Promise<boolean> {
return null;
}
public setSpellCheckLanguages(preferredLangs: string[]) {} public setSpellCheckLanguages(preferredLangs: string[]) {}
public getSpellCheckLanguages(): Promise<string[]> | null { public getSpellCheckLanguages(): Promise<string[]> | null {

View File

@ -82,6 +82,8 @@ interface IProps {
// width. // width.
menuWidth?: number; menuWidth?: number;
searchEnabled?: boolean; searchEnabled?: boolean;
// Placeholder to show when no value is selected
placeholder?: string;
// Called when the selected option changes // Called when the selected option changes
onOptionChange(dropdownKey: string): void; onOptionChange(dropdownKey: string): void;
// Called when the value of the search field changes // Called when the value of the search field changes
@ -362,7 +364,7 @@ export default class Dropdown extends React.Component<IProps, IState> {
this.props.getShortOption(this.props.value) : this.props.getShortOption(this.props.value) :
this.childrenByKey[this.props.value]; this.childrenByKey[this.props.value];
currentValue = <div className="mx_Dropdown_option" id={`${this.props.id}_value`}> currentValue = <div className="mx_Dropdown_option" id={`${this.props.id}_value`}>
{ selectedChild } { selectedChild || this.props.placeholder }
</div>; </div>;
} }

View File

@ -116,7 +116,9 @@ export default class SpellCheckLanguagesDropdown extends React.Component<SpellCh
onSearchChange={this.onSearchChange} onSearchChange={this.onSearchChange}
searchEnabled={true} searchEnabled={true}
value={value} value={value}
label={_t("Language Dropdown")}> label={_t("Language Dropdown")}
placeholder={_t("Choose a locale")}
>
{ options } { options }
</Dropdown>; </Dropdown>;
} }

View File

@ -25,7 +25,7 @@ interface IProps {
checked: boolean; checked: boolean;
// Whether or not the user can interact with the switch // Whether or not the user can interact with the switch
disabled: boolean; disabled?: boolean;
// Called when the checked state changes. First argument will be the new state. // Called when the checked state changes. First argument will be the new state.
onChange(checked: boolean): void; onChange(checked: boolean): void;

View File

@ -72,6 +72,7 @@ export default class SpellCheckLanguages extends React.Component<SpellCheckLangu
e.preventDefault(); e.preventDefault();
const language = this.state.newLanguage; const language = this.state.newLanguage;
this.setState({ newLanguage: "" });
if (!language) return; if (!language) return;
if (this.props.languages.includes(language)) return; if (this.props.languages.includes(language)) return;

View File

@ -50,6 +50,8 @@ import ChangePassword from "../../ChangePassword";
import InlineTermsAgreement from "../../../terms/InlineTermsAgreement"; import InlineTermsAgreement from "../../../terms/InlineTermsAgreement";
import SetIdServer from "../../SetIdServer"; import SetIdServer from "../../SetIdServer";
import SetIntegrationManager from "../../SetIntegrationManager"; import SetIntegrationManager from "../../SetIntegrationManager";
import ToggleSwitch from "../../../elements/ToggleSwitch";
import { IS_MAC } from "../../../../../Keyboard";
interface IProps { interface IProps {
closeSettingsFn: () => void; closeSettingsFn: () => void;
@ -57,6 +59,7 @@ interface IProps {
interface IState { interface IState {
language: string; language: string;
spellCheckEnabled: boolean;
spellCheckLanguages: string[]; spellCheckLanguages: string[];
haveIdServer: boolean; haveIdServer: boolean;
serverSupportsSeparateAddAndBind: boolean; serverSupportsSeparateAddAndBind: boolean;
@ -85,6 +88,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
this.state = { this.state = {
language: languageHandler.getCurrentLanguage(), language: languageHandler.getCurrentLanguage(),
spellCheckEnabled: false,
spellCheckLanguages: [], spellCheckLanguages: [],
haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()), haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()),
serverSupportsSeparateAddAndBind: null, serverSupportsSeparateAddAndBind: null,
@ -126,10 +130,16 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
} }
public async componentDidMount(): Promise<void> { public async componentDidMount(): Promise<void> {
const plaf = PlatformPeg.get(); const plat = PlatformPeg.get();
if (plaf) { const [spellCheckEnabled, spellCheckLanguages] = await Promise.all([
plat.getSpellCheckEnabled(),
plat.getSpellCheckLanguages(),
]);
if (spellCheckLanguages) {
this.setState({ this.setState({
spellCheckLanguages: await plaf.getSpellCheckLanguages(), spellCheckEnabled,
spellCheckLanguages,
}); });
} }
} }
@ -238,11 +248,12 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
private onSpellCheckLanguagesChange = (languages: string[]): void => { private onSpellCheckLanguagesChange = (languages: string[]): void => {
this.setState({ spellCheckLanguages: languages }); this.setState({ spellCheckLanguages: languages });
PlatformPeg.get()?.setSpellCheckLanguages(languages);
};
const plaf = PlatformPeg.get(); private onSpellCheckEnabledChange = (spellCheckEnabled: boolean): void => {
if (plaf) { this.setState({ spellCheckEnabled });
plaf.setSpellCheckLanguages(languages); PlatformPeg.get()?.setSpellCheckEnabled(spellCheckEnabled);
}
}; };
private onPasswordChangeError = (err): void => { private onPasswordChangeError = (err): void => {
@ -368,12 +379,18 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
private renderSpellCheckSection(): JSX.Element { private renderSpellCheckSection(): JSX.Element {
return ( return (
<div className="mx_SettingsTab_section"> <div className="mx_SettingsTab_section mx_SettingsTab_section_spellcheck">
<span className="mx_SettingsTab_subheading">{ _t("Spell check dictionaries") }</span> <span className="mx_SettingsTab_subheading">
<SpellCheckSettings { _t("Spell check") }
<ToggleSwitch
checked={this.state.spellCheckEnabled}
onChange={this.onSpellCheckEnabledChange}
/>
</span>
{ (this.state.spellCheckEnabled && !IS_MAC) && <SpellCheckSettings
languages={this.state.spellCheckLanguages} languages={this.state.spellCheckLanguages}
onLanguagesChange={this.onSpellCheckLanguagesChange} onLanguagesChange={this.onSpellCheckLanguagesChange}
/> /> }
</div> </div>
); );
} }
@ -449,7 +466,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
public render(): JSX.Element { public render(): JSX.Element {
const plaf = PlatformPeg.get(); const plaf = PlatformPeg.get();
const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck(); const supportsMultiLanguageSpellCheck = plaf.supportsSpellCheckSettings();
const discoWarning = this.state.requiredPolicyInfo.hasTerms const discoWarning = this.state.requiredPolicyInfo.hasTerms
? <img ? <img

View File

@ -1435,7 +1435,7 @@
"Set a new account password...": "Set a new account password...", "Set a new account password...": "Set a new account password...",
"Account": "Account", "Account": "Account",
"Language and region": "Language and region", "Language and region": "Language and region",
"Spell check dictionaries": "Spell check dictionaries", "Spell check": "Spell check",
"Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.", "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.",
"Account management": "Account management", "Account management": "Account management",
"Deactivating your account is a permanent action — be careful!": "Deactivating your account is a permanent action — be careful!", "Deactivating your account is a permanent action — be careful!": "Deactivating your account is a permanent action — be careful!",
@ -2377,6 +2377,7 @@
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.": "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.", "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.": "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use %(brand)s with an existing Matrix account on a different homeserver.",
"Join millions for free on the largest public server": "Join millions for free on the largest public server", "Join millions for free on the largest public server": "Join millions for free on the largest public server",
"Homeserver": "Homeserver", "Homeserver": "Homeserver",
"Choose a locale": "Choose a locale",
"Continue with %(provider)s": "Continue with %(provider)s", "Continue with %(provider)s": "Continue with %(provider)s",
"Sign in with single sign-on": "Sign in with single sign-on", "Sign in with single sign-on": "Sign in with single sign-on",
"And %(count)s more...|other": "And %(count)s more...", "And %(count)s more...|other": "And %(count)s more...",