diff --git a/_locales/en/messages.json b/_locales/en/messages.json index bf39fa7c8..534ed9e7a 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1317,23 +1317,30 @@ "message": "Permissions", "description": "Header for permissions section of settings" }, - "mediaPermissionsDescription": { - "message": "Allow access to camera and microphone", - "description": "Description of the media permission description" - }, "general": { "message": "General", "description": "Header for general options on the settings screen" }, - "linkPreviews": { + "linkPreviewsTitle": { "message": "Link Previews", "description": "Option to control creation and send of link previews in setting screen" }, - "linkPreviewsSettingDescription": { + "linkPreviewDescription": { "message": "Enable link previews", "description": "Description shown for the Link Preview option " }, + "mediaPermissionsTitle": { + "message": "Microphone and Camera" + }, + "mediaPermissionsDescription": { + "message": "Allow access to camera and microphone", + "description": "Description of the media permission description" + }, + "spellCheckTitle": { + "message": "Spell Check", + "description": "Description of the media permission description" + }, "spellCheckDescription": { "message": "Enable spell check of text entered in message composition box", "description": "Description of the media permission description" @@ -1399,7 +1406,7 @@ "description": "Warning for the time to live setting" }, "notificationSettingsDialog": { - "message": "When messages arrive, display notifications that reveal:", + "message": "When messages arrive, display notifications that reveal...", "description": "Explain the purpose of the notification settings" }, "disableNotifications": { @@ -1836,12 +1843,22 @@ "message": "Dark", "description": "Label text for dark theme" }, + "themeToggleTitle" : { + "message": "Light Mode" + }, + "themeToggleDescription" : { + "message": "Choose the theme best suited to you" + }, "noteToSelf": { "message": "Note to Self", "description": "Name for the conversation with your own phone number" }, - "hideMenuBar": { - "message": "Hide menu bar", + "hideMenuBarTitle": { + "message": "Hide Menu Bar", + "description": "Label text for menu bar visibility setting" + }, + "hideMenuBarDescription": { + "message": "Toggle system menu bar visibility", "description": "Label text for menu bar visibility setting" }, "startConversation": { @@ -2481,7 +2498,7 @@ "message": "Decline" }, "generalSettingsTitle": { - "message": "Generals" + "message": "General" }, "generalSettingsDescription": { "message": "General settings and configuration" @@ -2492,11 +2509,17 @@ "accountSettingsDescription": { "message": "Manage your account" }, + "permissionSettingsTitle": { + "message": "Permissions" + }, + "permissionSettingsDescription": { + "message": "Set Session's permissions" + }, "privacySettingsTitle": { "message": "Privacy" }, "privacySettingsDescription": { - "message": "Privacy description" + "message": "Manage your privacy settings" }, "notificationSettingsTitle": { "message": "Notifications" diff --git a/js/background.js b/js/background.js index 8f8738fc4..504912f6a 100644 --- a/js/background.js +++ b/js/background.js @@ -911,6 +911,20 @@ window.Events.setHideMenuBar(newValue); } + window.toggleSpellCheck = () => { + const newValue = ! window.getSettingValue('spell-check'); + window.Events.setSpellCheck(newValue); + } + + window.toggleLinkPreview = () => { + const newValue = ! window.getSettingValue('link-preview-setting'); + window.Events.setLinkPreviewSetting(newValue); + } + + window.toggleMediaPermissions= () => { + + } + window.sendGroupInvitations = (serverInfo, pubkeys) => { pubkeys.forEach(async pubkey => { const convo = await ConversationController.getOrCreateAndWait( diff --git a/js/views/settings_view.js b/js/views/settings_view.js index f1d254196..af89d9f95 100644 --- a/js/views/settings_view.js +++ b/js/views/settings_view.js @@ -249,8 +249,8 @@ spellCheckHeader: i18n('spellCheck'), spellCheckDescription: i18n('spellCheckDescription'), blockedHeader: 'Blocked Users', - linkPreviews: i18n('linkPreviews'), - linkPreviewsSettingDescription: i18n('linkPreviewsSettingDescription'), + linkPreviews: i18n('linkPreviewsTitle'), + linkPreviewsSettingDescription: i18n('linkPreviewsDescription'), }; }, onClose() { diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index e2a5cbbfc..9c607e285 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -1002,6 +1002,8 @@ label { &__title { line-height: 1.7; + font-size: 16px; + font-weight: bold; } &__description { @@ -1009,6 +1011,12 @@ label { font-weight: 100; @include session-color-subtle($session-color-white); } + + &__content{ + label { + @include session-color-subtle($session-color-white); + } + } } } @@ -1068,12 +1076,24 @@ label { } } + +.session-radio-group fieldset { + border: none; + margin-left: $session-margin-sm; + margin-top: $session-margin-sm; + + .session-radio { + padding: $session-margin-xs 0px; + } +} + .session-radio { input[type="radio"] { border: 0; opacity: 0; padding: 0; position: absolute; + cursor: pointer; } label { @@ -1085,10 +1105,10 @@ label { display: inline-block; width: 0.5em; height: 0.5em; - margin-right: 0.5em; + margin-right: 0.80em; border-radius: 100%; vertical-align: -3px; - border: 2px solid $session-color-white; + border: 2px solid rgba($session-color-white, 0.6); padding: 0.2em; background-color: transparent; background-clip: content-box; @@ -1106,4 +1126,5 @@ label { label:before { transition: all $session-transition-duration ease; } -} \ No newline at end of file +} + diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx index 675d5c205..39c85f160 100644 --- a/ts/components/session/LeftPaneSettingSection.tsx +++ b/ts/components/session/LeftPaneSettingSection.tsx @@ -173,26 +173,21 @@ export class LeftPaneSettingSection extends React.Component { title: window.i18n('generalSettingsTitle'), description: window.i18n('generalSettingsDescription'), }, - { - id: SessionSettingCategory.Account, - title: window.i18n('accountSettingsTitle'), - description: window.i18n('accountSettingsDescription'), - }, { id: SessionSettingCategory.Privacy, title: window.i18n('privacySettingsTitle'), description: window.i18n('privacySettingsDescription'), }, + { + id: SessionSettingCategory.Permissions, + title: window.i18n('permissionSettingsTitle'), + description: window.i18n('permissionSettingsDescription'), + }, { id: SessionSettingCategory.Notifications, title: window.i18n('notificationSettingsTitle'), description: window.i18n('notificationSettingsDescription'), }, - { - id: SessionSettingCategory.Devices, - title: window.i18n('devicesSettingsTitle'), - description: window.i18n('devicesSettingsDescription'), - }, ]; } diff --git a/ts/components/session/SessionRadio.tsx b/ts/components/session/SessionRadio.tsx index 1e84b4fe7..14436e028 100644 --- a/ts/components/session/SessionRadio.tsx +++ b/ts/components/session/SessionRadio.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import classNames from 'classnames'; - interface Props { label: string; + value: string; active: boolean; + group?: string; + onClick: any; } interface State { @@ -12,6 +13,10 @@ interface State { } export class SessionRadio extends React.PureComponent { + public static defaultProps = { + onClick: () => null, + } + constructor(props: any) { super(props); this.clickHandler = this.clickHandler.bind(this); @@ -23,20 +28,32 @@ export class SessionRadio extends React.PureComponent { public render() { const active = this.state.active; - const { label } = this.props; + const { label, group, value } = this.props; return ( -
- +
+
); } - private clickHandler() { - this.setState({ - active: !this.state.active, - }); + private clickHandler(e: any) { + if (this.props.onClick) { + e.stopPropagation(); + this.props.onClick(); + + this.setState({ + active: !this.state.active, + }); + + } } } diff --git a/ts/components/session/SessionRadioGroup.tsx b/ts/components/session/SessionRadioGroup.tsx index d2d316445..4a256f3a4 100644 --- a/ts/components/session/SessionRadioGroup.tsx +++ b/ts/components/session/SessionRadioGroup.tsx @@ -1,12 +1,16 @@ import React from 'react'; -import classNames from 'classnames'; + +import { SessionRadio } from './SessionRadio'; interface Props { - activeItem: Number; + initalItem: string; + items: Array; + group: string; + onClick?: any; } interface State { - activeItem: Number; + activeItem: string; } export class SessionRadioGroup extends React.PureComponent { @@ -17,23 +21,41 @@ export class SessionRadioGroup extends React.PureComponent { constructor(props: any) { super(props); this.clickHandler = this.clickHandler.bind(this); + + this.state = { + activeItem: this.props.initalItem, + } } public render() { + const { items, group } = this.props; + return (
- +
+ { items.map(item => { + return ( + + ); + }) + } +
); } - private clickHandler(e: any) { - return; + private clickHandler() { + if (this.props.onClick) { + this.props.onClick(); + } } } diff --git a/ts/components/session/settings/SessionSettingListItem.tsx b/ts/components/session/settings/SessionSettingListItem.tsx index f86a4bf09..219695bf6 100644 --- a/ts/components/session/settings/SessionSettingListItem.tsx +++ b/ts/components/session/settings/SessionSettingListItem.tsx @@ -2,10 +2,10 @@ import React from 'react'; import classNames from 'classnames'; import { SessionToggle } from '../SessionToggle'; -import { SessionButton, SessionButtonColor } from '../SessionButton'; +import { SessionButton } from '../SessionButton'; import { SessionSettingType } from './SessionSettings'; -import { SessionRadio } from '../SessionRadio'; +import { SessionRadioGroup } from '../SessionRadioGroup'; interface Props { title: string; @@ -14,9 +14,7 @@ interface Props { value: any; options?: Array; onClick?: any; - inline?: boolean; - buttonText?: string; - buttonColor?: SessionButtonColor; + content: any; } export class SessionSettingListItem extends React.Component { @@ -37,15 +35,15 @@ export class SessionSettingListItem extends React.Component { description, type, value, - inline, - buttonText, - buttonColor, + content, } = this.props; + const inline = ![SessionSettingType.Options, SessionSettingType.Slider].includes(type); + return ( -
-
-
{title}
+
+
+
{title}
{description && (
@@ -54,26 +52,30 @@ export class SessionSettingListItem extends React.Component { )}
- {type === SessionSettingType.Toggle && ( -
- -
- )} +
+ {type === SessionSettingType.Toggle && ( +
+ +
+ )} - {type === SessionSettingType.Button && ( - - )} + {type === SessionSettingType.Button && ( + + )} - {type === SessionSettingType.Options && ( - - )} + {type === SessionSettingType.Options && ( + + )} +
); } diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index 11f79f318..3f25d5c89 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -3,11 +3,11 @@ import React from 'react'; import { SettingsHeader } from './SessionSettingsHeader'; import { SessionSettingListItem } from './SessionSettingListItem'; - export enum SessionSettingCategory { General = 'general', Account = 'account', Privacy = 'privacy', + Permissions = 'permissions', Notifications = 'notifications', Devices = 'devices', } @@ -42,54 +42,86 @@ export class SettingsView extends React.Component { const localSettings = [ { id: 'theme-setting', - title: 'Light Mode', + title: window.i18n('themeToggleTitle'), description: 'Choose the theme best suited to you', hidden: true, comparisonValue: 'light', - type: SessionSettingType.Options, + type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleTheme, - childProps: {}, + content: {}, }, { id: 'hide-menu-bar', - title: 'Hide Menu Bar', - description: 'Toggle system menu bar visibi', + title: window.i18n('hideMenuBarTitle'), + description: window.i18n('hideMenuBarDescription'), hidden: !Settings.isHideMenuBarSupported(), type: SessionSettingType.Toggle, category: SessionSettingCategory.General, setFn: window.toggleMenuBar, - childProps: {}, + content: {}, + }, + { + id: 'spell-check', + title: window.i18n('spellCheckTitle'), + description: window.i18n('spellCheckDescription'), + hidden: false, + type: SessionSettingType.Toggle, + category: SessionSettingCategory.General, + setFn: window.toggleSpellCheck, + content: {}, + }, + { + id: 'link-preview-setting', + title: window.i18n('linkPreviewsTitle'), + description: window.i18n('linkPreviewDescription'), + hidden: false, + type: SessionSettingType.Toggle, + category: SessionSettingCategory.General, + setFn: window.toggleLinkPreview, + content: {}, }, + { id: 'notification-setting', - title: 'Notifications', - description: 'When messages arive, display notifications that reveal:', + title: window.i18n('notificationSettingsDialog'), type: SessionSettingType.Options, category: SessionSettingCategory.Notifications, - setFn: () => window.setSettingValue(this.getNotificationPreference()), - childProps: { - options: [ - { - id: 'default', - desc: 'Both sender name and message', - }, - { - id: 'name', - desc: 'Only sender name', - }, - { - id: 'count', - desc: 'Neither name nor messsage', - }, - { - id: 'off', - desc: 'Disable notificationss', - }, - ], - activeIndex: 0 + setFn: () => this.setOptionsSetting('notification-setting'), + content: { + options: { + group: 'notification-setting', + initalItem: window.getSettingValue('notification-setting'), + items: [{ + label: window.i18n('nameAndMessage'), + value: 'message' + },{ + label: window.i18n('nameOnly'), + value: 'name' + },{ + label: window.i18n('noNameOrMessage'), + value: 'count' + },{ + label: window.i18n('disableNotifications'), + value: 'off' + }], + }, }, }, + + + { + id: 'media-permissions', + title: window.i18n('mediaPermissionsTitle'), + description: window.i18n('mediaPermissionsDescription'), + hidden: false, + type: SessionSettingType.Toggle, + category: SessionSettingCategory.Permissions, + setFn: window.toggleMediaPermissions, + content: {}, + }, + + ]; return ( @@ -103,14 +135,13 @@ export class SettingsView extends React.Component { {renderSettings && !(setting.hidden) && ( { this.updateSetting(setting); }} - buttonText={setting.childProps.buttonText || undefined} - buttonColor={setting.childProps.buttonColor || undefined} + content={setting.content || undefined} /> )}
@@ -134,27 +165,25 @@ export class SettingsView extends React.Component { } public updateSetting(item: any) { - if (item.type === SessionSettingType.Toggle) { - // If no custom afterClick function given, alter values in storage here - if (!item.setFn) { - // Switch to opposite state - const newValue = !window.getSettingValue(item.id); - window.setSettingValue(item.id, newValue); - } - } // If there's a custom afterClick function, // execute it instead of automatically updating settings if (item.setFn) { item.setFn(); + } else { + if (item.type === SessionSettingType.Toggle) { + // If no custom afterClick function given, alter values in storage here + // Switch to opposite state + const newValue = !window.getSettingValue(item.id); + window.setSettingValue(item.id, newValue); + } } - return; } - public getNotificationPreference(){ - const value = window.getSettingValue('notification-setting'); - return value || 'default'; + public setOptionsSetting(settingID: string){ + const selectedValue = $(`#${settingID} .session-radio input:checked`).val(); + window.setSettingValue(settingID, selectedValue); } } diff --git a/ts/global.d.ts b/ts/global.d.ts index dae15b102..d9f420fa5 100644 --- a/ts/global.d.ts +++ b/ts/global.d.ts @@ -26,6 +26,9 @@ interface Window { deleteAccount: any; toggleTheme: any; toggleMenuBar: any; + toggleSpellCheck: any; + toggleLinkPreview: any; + toggleMediaPermissions: any; getSettingValue: any; setSettingValue: any;