add config option to send on Enter vs send on CTRL-Enter

This commit is contained in:
or-else
2025-08-10 15:25:05 +03:00
parent 0b05d480c7
commit 79a1bc98b2
71 changed files with 891 additions and 232 deletions
@@ -2,17 +2,21 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
export default class AccAppearanceView extends React.PureComponent {
export default class AccGeneralView extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
colorSchema: props.colorSchema || 'light dark',
textSize: (props.textSize * 10) || '100',
sendOnEnter: props.sendOnEnter || 'plain',
};
this.isMac = ((navigator.userAgentData && navigator.userAgentData.platform)
|| navigator.platform).toLowerCase().startsWith('mac');
this.handleColorSchemaSelected = this.handleColorSchemaSelected.bind(this);
this.handleTextSizeChanged = this.handleTextSizeChanged.bind(this);
this.handleSendOnEnterSelected = this.handleSendOnEnterSelected.bind(this);
}
handleColorSchemaSelected(e) {
@@ -27,6 +31,12 @@ export default class AccAppearanceView extends React.PureComponent {
this.props.onTextSizeChanged((e.currentTarget.value / 10) | 0);
}
handleSendOnEnterSelected(e) {
console.log('handleSendOnEnterSelected', e.currentTarget.value);
this.setState({sendOnEnter: e.currentTarget.value});
this.props.onSendOnEnterChanged(e.currentTarget.value);
}
render() {
return (
<div id="settings-form" className="scrollable-panel">
@@ -40,7 +50,7 @@ export default class AccAppearanceView extends React.PureComponent {
<ul className="quoted">
<li key="system">
<input type="radio" id="system" name="color-scheme-select" value="light dark"
checked={this.state.colorSchema === 'light dark'}
checked={this.state.colorSchema == 'light dark'}
onChange={this.handleColorSchemaSelected} />&nbsp;
<label htmlFor="system">
<FormattedMessage id="color_schema_system" defaultMessage="System default" description="Name of the color schema"/>&nbsp;
@@ -49,7 +59,7 @@ export default class AccAppearanceView extends React.PureComponent {
</li>
<li key="light">
<input type="radio" id="light" name="color-scheme-select" value="light"
checked={this.state.colorSchema === 'light'}
checked={this.state.colorSchema == 'light'}
onChange={this.handleColorSchemaSelected} />&nbsp;
<label htmlFor="light">
<FormattedMessage id="color_schema_light" defaultMessage="Light" description="Name of the color schema"/>&nbsp;
@@ -58,7 +68,7 @@ export default class AccAppearanceView extends React.PureComponent {
</li>
<li key="dark">
<input type="radio" id="dark" name="color-scheme-select" value="dark"
checked={this.state.colorSchema === 'dark'}
checked={this.state.colorSchema == 'dark'}
onChange={this.handleColorSchemaSelected} />&nbsp;
<label htmlFor="dark">
<FormattedMessage id="color_schema_dark" defaultMessage="Dark" description="Name of the color schema"/>&nbsp;
@@ -89,6 +99,48 @@ export default class AccAppearanceView extends React.PureComponent {
</datalist>
</div>
</div>
<div className="hr" />
<div className="panel-form-row">
<label className="small">
<FormattedMessage id="label_keyboard" defaultMessage="Keyboard:"
description="Label for send on enter settings" />
</label>
</div>
<div className="panel-form-row">
<ul className="quoted">
<li key="plain">
<input type="radio" id="plain" name="send-select" value="plain"
checked={this.state.sendOnEnter == 'plain'}
onChange={this.handleSendOnEnterSelected} />&nbsp;
<label htmlFor="send_plain">
<FormattedMessage id="send_plain" defaultMessage="Send on Enter"
description="Config option to send message on hitting Enter"/>&nbsp;
</label>
<div className="panel-form-row">
<span className="small gray">
<FormattedMessage id="send_plain_explained" defaultMessage="Press Shift + Enter for new line"
description="Explanation how to enter newline when [Send on Enter] is enabled" />
</span>
</div>
</li>
<li key="command">
<input type="radio" id="command" name="send-select" value="command"
checked={this.state.sendOnEnter == 'command'}
onChange={this.handleSendOnEnterSelected} />&nbsp;
<label htmlFor="send_command">
<FormattedMessage id="send_command" defaultMessage="Send on {key}"
values={{key: this.isMac ? '⌘ + Enter' : 'Ctrl + Enter'}}
description="Config option to send message on hitting CTRL(or Cmd)-Enter"/>&nbsp;
</label>
<div className="panel-form-row">
<span className="small gray">
<FormattedMessage id="send_command_explained" defaultMessage="Press Enter for new line"
description="Explanation how to enter newline when [Send on CTRL-Enter] is enabled" />
</span>
</div>
</li>
</ul>
</div>
</div>
);
}
+1 -1
View File
@@ -124,7 +124,7 @@ class AccSecurityView extends React.Component {
checked={this.props.incognitoMode} onChange={this.handleCheckboxClick} />
</div>
<div className="panel-form-row">
<span className="small">
<span className="small gray">
<FormattedMessage id="incognito_mode_description" defaultMessage="Hide your online status and typing indicators."
description="Description for incognito mode toggle" />
</span>
+3 -3
View File
@@ -148,9 +148,9 @@ export default class AccountSettingsView extends React.Component {
</div>
<div className="hr" />
<div className="panel-form-column">
<a href="#" className="flat-button" onClick={e => {e.preventDefault(); this.props.onNavigate('appearance');}}>
<i className="material-icons">tune</i>&nbsp;<FormattedMessage id="sidepanel_title_appearance"
defaultMessage="Appearance" description="Sidepanel title for AccAppearanceView." />
<a href="#" className="flat-button" onClick={e => {e.preventDefault(); this.props.onNavigate('acc_general');}}>
<i className="material-icons">tune</i>&nbsp;<FormattedMessage id="sidepanel_title_acc_general"
defaultMessage="General" description="Sidepanel title for AccGeneralView." />
</a>
<a href="#" className="flat-button" onClick={e => {e.preventDefault(); this.props.onNavigate('notif');}}>
<i className="material-icons">notifications</i>&nbsp;<FormattedMessage id="sidepanel_title_acc_notifications"
+1
View File
@@ -1712,6 +1712,7 @@ class MessagesView extends React.Component {
disabled={!this.state.isWriter || this.state.deleted}
reply={this.state.reply}
initMessage={this.state.contentToEdit}
sendOnEnter={this.props.sendOnEnter}
onKeyPress={this.sendKeyPress}
onRecordingProgress={this.sendKeyPress}
onSendMessage={this.sendMessage}
+10 -8
View File
@@ -9,7 +9,7 @@ import TopicCommonView from './topic-common-view.jsx';
const AccountSettingsView = React.lazy(_ => import('./account-settings-view.jsx'));
import ContactsView from './contacts-view.jsx';
const CreateAccountView = React.lazy(_ => import('./create-account-view.jsx'));
import AccAppearanceView from './acc-appearance-view.jsx';
import AccGeneralView from './acc-general-view.jsx';
import AccNotificationsView from './acc-notifications-view.jsx';
const AccSecurityView = React.lazy(_ => import('./acc-security-view.jsx'));
import AccSupportView from './acc-support-view.jsx';
@@ -61,10 +61,10 @@ const messages = defineMessages({
description: 'Sidepanel title for AccNotificationsView.',
defaultMessage: 'Notifications'
},
appearance: {
id: 'sidepanel_title_appearance',
description: 'Sidepanel title for AccAppearanceView.',
defaultMessage: 'Appearance'
acc_general: {
id: 'sidepanel_title_acc_general',
description: 'Sidepanel title for AccGeneralView.',
defaultMessage: 'General'
},
support: {
id: 'sidepanel_title_acc_support',
@@ -206,12 +206,14 @@ class SidepanelView extends React.PureComponent {
onUpdateTagsRequest={this.props.onUpdateAccountTags}
onError={this.props.onError} /> :
view === 'appearance' ?
<AccAppearanceView
view === 'acc_general' ?
<AccGeneralView
colorSchema={this.props.colorSchema}
textSize={this.props.textSize}
sendOnEnter={this.props.sendOnEnter}
onChangeColorSchema={this.props.onChangeColorSchema}
onTextSizeChanged={this.props.onTextSizeChanged} /> :
onTextSizeChanged={this.props.onTextSizeChanged}
onSendOnEnterChanged={this.props.onSendOnEnterChanged} /> :
view === 'notif' ?
<AccNotificationsView
+12 -3
View File
@@ -136,6 +136,7 @@ class TinodeWeb extends React.Component {
this.handleToggleIncognitoMode = this.handleToggleIncognitoMode.bind(this);
this.handleChangeColorSchema = this.handleChangeColorSchema.bind(this);
this.handleChangeTextSize = this.handleChangeTextSize.bind(this);
this.handleSendOnEnter = this.handleSendOnEnter.bind(this);
this.handleSettings = this.handleSettings.bind(this);
this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
this.handleShowArchive = this.handleShowArchive.bind(this);
@@ -217,6 +218,7 @@ class TinodeWeb extends React.Component {
incognitoMode: false,
colorSchema: settings.colorSchema || DEFAULT_COLOR_SCHEME, // default: system default
textSize: settings.textSize || DEFAULT_TEXT_SIZE, // default size: 10pt
sendOnEnter: settings.sendOnEnter || 'plain', // default: 'plain' (just Enter)
// Persistent request to enable alerts.
desktopAlerts: persist && !!settings.desktopAlerts,
// Enable / disable checkbox.
@@ -524,7 +526,7 @@ class TinodeWeb extends React.Component {
if (hash.path && hash.path.length > 0) {
// Left-side panel selector.
if (['register','settings','edit','notif','appearance','security','support','general','crop',
if (['register','settings','edit','notif','acc_general','security','support','general','crop',
'cred','reset','newtpk','archive','blocked','contacts',''].includes(hash.path[0])) {
newState.sidePanelSelected = hash.path[0];
} else {
@@ -1223,6 +1225,11 @@ class TinodeWeb extends React.Component {
document.documentElement.style.setProperty('--message-text-size', `${size}pt`);
}
handleSendOnEnter(option) {
this.setState({sendOnEnter: option});
LocalStorageUtil.updateObject('settings', {sendOnEnter: option});
}
handleUpdateAccountTagsRequest(_, tags) {
this.tinode.getMeTopic().setMeta({tags: tags})
.catch(err => this.handleError(err.message, 'err'));
@@ -1335,7 +1342,7 @@ class TinodeWeb extends React.Component {
handleSidepanelCancel() {
const parsed = HashNavigation.parseUrlHash(window.location.hash);
let path = '';
if (['security','support','general','notif','appearance'].includes(parsed.path[0])) {
if (['security','support','general','notif','acc_general'].includes(parsed.path[0])) {
path = 'edit';
} else if ('crop' == parsed.path[0]) {
path = 'general';
@@ -2084,6 +2091,7 @@ class TinodeWeb extends React.Component {
reqCredMethod={this.state.reqCredMethod}
textSize={this.state.textSize}
colorSchema={this.state.colorSchema}
sendOnEnter={this.state.sendOnEnter}
onGlobalSettings={this.handleGlobalSettings}
onSignUp={this.handleNewAccount}
@@ -2100,6 +2108,7 @@ class TinodeWeb extends React.Component {
onToggleIncognitoMode={this.handleToggleIncognitoMode}
onChangeColorSchema={this.handleChangeColorSchema}
onTextSizeChanged={this.handleChangeTextSize}
onSendOnEnterChanged={this.handleSendOnEnter}
onCredAdd={this.handleCredAdd}
onCredDelete={this.handleCredDelete}
onCredConfirm={this.handleCredConfirm}
@@ -2142,7 +2151,7 @@ class TinodeWeb extends React.Component {
serverAddress={this.state.serverAddress}
applicationVisible={this.state.applicationVisible}
colorSchema={this.state.colorSchema}
sendOnEnter={this.state.sendOnEnter}
forwardMessage={this.state.forwardMessage}
onCancelForwardMessage={this.handleHideForwardDialog}