feat: update design of the Notification Settings screen

the preview button is not linked yet
This commit is contained in:
Audric Ackermann 2022-08-22 16:09:34 +10:00
parent 9eae1289c7
commit 13bf0e073d
15 changed files with 110 additions and 51 deletions

View file

@ -335,7 +335,8 @@
"appearanceSettingsTitle": "Appearance", "appearanceSettingsTitle": "Appearance",
"privacySettingsTitle": "Privacy", "privacySettingsTitle": "Privacy",
"notificationsSettingsTitle": "Notifications", "notificationsSettingsTitle": "Notifications",
"notificationsSettingsContent": "Notifications Content", "notificationsSettingsContent": "Notification Content",
"notificationPreview": "Preview",
"recoveryPhraseEmpty": "Enter your recovery phrase", "recoveryPhraseEmpty": "Enter your recovery phrase",
"displayNameEmpty": "Please enter a display name", "displayNameEmpty": "Please enter a display name",
"members": "$count$ members", "members": "$count$ members",

View file

@ -1,8 +1,6 @@
#!/bin/python3 #!/bin/python3
# usage : ./tools/compareLocalizedStrings.py en de
import re import re
from os import path, listdir from os import path, listdir
from glob import glob from glob import glob
@ -23,6 +21,7 @@ with open(EN_FILE,'r') as jsonFile:
stringToWrite += json.dumps(keys, sort_keys=True).replace(',', '\n |').replace('"', '\'')[1:-1] stringToWrite += json.dumps(keys, sort_keys=True).replace(',', '\n |').replace('"', '\'')[1:-1]
stringToWrite += ';\n' stringToWrite += ';\n'
# print(stringToWrite) # print(stringToWrite)
with open(LOCALIZED_KEYS_FILE, "w") as typeFile: with open(LOCALIZED_KEYS_FILE, "w") as typeFile:

View file

@ -257,7 +257,7 @@ async function fetchReleaseFromFSAndUpdateMain() {
async function askEnablingOpengroupPruningIfNeeded() { async function askEnablingOpengroupPruningIfNeeded() {
if (Storage.get(SettingsKey.settingsOpengroupPruning) === undefined) { if (Storage.get(SettingsKey.settingsOpengroupPruning) === undefined) {
const setSettingsAndCloseDialog = async (valueToSetPruningTo: boolean) => { const setSettingsAndCloseDialog = async (valueToSetPruningTo: boolean) => {
window.setSettingValue(SettingsKey.settingsOpengroupPruning, valueToSetPruningTo); await window.setSettingValue(SettingsKey.settingsOpengroupPruning, valueToSetPruningTo);
await window.setOpengroupPruning(valueToSetPruningTo); await window.setOpengroupPruning(valueToSetPruningTo);
window.inboxStore?.dispatch(updateConfirmModal(null)); window.inboxStore?.dispatch(updateConfirmModal(null));
}; };

View file

@ -1,42 +1,99 @@
import React from 'react'; import React from 'react';
// tslint:disable-next-line: no-submodule-imports
import useUpdate from 'react-use/lib/useUpdate';
import styled from 'styled-components';
import { SettingsKey } from '../../data/settings-key';
import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton';
import { SessionRadioGroup } from '../basic/SessionRadioGroup'; import { SessionRadioGroup } from '../basic/SessionRadioGroup';
import { SessionSettingsItemWrapper } from './SessionSettingListItem'; import { SpacerLG } from '../basic/Text';
import { SessionSettingsItemWrapper, SessionToggleWithDescription } from './SessionSettingListItem';
// tslint:disable: use-simple-attributes
enum NOTIFICATION {
MESSAGE = 'message',
NAME = 'name',
COUNT = 'count',
OFF = 'off',
}
const StyledButtonContainer = styled.div`
display: flex;
width: min-content;
flex-direction: column;
padding-inline-start: var(--margins-lg);
`;
export const SessionNotificationGroupSettings = (props: { hasPassword: boolean | null }) => { export const SessionNotificationGroupSettings = (props: { hasPassword: boolean | null }) => {
const forceUpdate = useUpdate();
if (props.hasPassword === null) { if (props.hasPassword === null) {
return null; return null;
} }
const initialItem =
window.getSettingValue(SettingsKey.settingsNotification) || NOTIFICATION.MESSAGE;
const initialItem = window.getSettingValue('notification-setting') || 'message'; const notificationsAreEnabled = initialItem && initialItem !== NOTIFICATION.OFF;
const onClickPreview = () => {
if (!notificationsAreEnabled) {
return;
}
};
const items = [ const items = [
{ {
label: window.i18n('nameAndMessage'), label: window.i18n('nameAndMessage'),
value: 'message', value: NOTIFICATION.MESSAGE,
}, },
{ {
label: window.i18n('nameOnly'), label: window.i18n('nameOnly'),
value: 'name', value: NOTIFICATION.NAME,
}, },
{ {
label: window.i18n('noNameOrMessage'), label: window.i18n('noNameOrMessage'),
value: 'count', value: NOTIFICATION.COUNT,
},
{
label: window.i18n('disableNotifications'),
value: 'off',
}, },
]; ];
return ( return (
<SessionSettingsItemWrapper title={window.i18n('notificationSettingsDialog')} inline={false}> <>
<SessionRadioGroup <SessionToggleWithDescription
initialItem={initialItem} onClickToggle={async () => {
group={'notification-setting'} await window.setSettingValue(
items={items} SettingsKey.settingsNotification,
onClick={(selectedRadioValue: string) => { notificationsAreEnabled ? NOTIFICATION.OFF : NOTIFICATION.MESSAGE
window.setSettingValue('notification-setting', selectedRadioValue); );
forceUpdate();
}} }}
title={window.i18n('notificationsSettingsTitle')}
active={notificationsAreEnabled}
/> />
</SessionSettingsItemWrapper> {notificationsAreEnabled ? (
<SessionSettingsItemWrapper
title={window.i18n('notificationsSettingsContent')}
description={window.i18n('notificationSettingsDialog')}
inline={false}
>
<SessionRadioGroup
initialItem={initialItem}
group={SettingsKey.settingsNotification}
items={items}
onClick={async (selectedRadioValue: string) => {
await window.setSettingValue(SettingsKey.settingsNotification, selectedRadioValue);
forceUpdate();
}}
/>
<StyledButtonContainer>
<SpacerLG />
<SessionButton
text={window.i18n('notificationPreview')}
buttonColor={SessionButtonColor.Green}
onClick={onClickPreview}
buttonType={SessionButtonType.BrandOutline}
/>
</StyledButtonContainer>
</SessionSettingsItemWrapper>
) : null}
</>
); );
}; };

View file

@ -58,7 +58,6 @@ export const SessionSettingsItemWrapper = (props: {
inline: boolean; inline: boolean;
title?: string; title?: string;
description?: string; description?: string;
isTypingMessageItem?: boolean;
children?: React.ReactNode; children?: React.ReactNode;
childrenDescription?: React.ReactNode; childrenDescription?: React.ReactNode;
}) => { }) => {

View file

@ -6,9 +6,9 @@ import { SessionSettingsItemWrapper } from './SessionSettingListItem';
export const ZoomingSessionSlider = (props: { onSliderChange?: (value: number) => void }) => { export const ZoomingSessionSlider = (props: { onSliderChange?: (value: number) => void }) => {
const forceUpdate = useUpdate(); const forceUpdate = useUpdate();
const handleSlider = (valueToForward: number) => { const handleSlider = async (valueToForward: number) => {
props?.onSliderChange?.(valueToForward); props?.onSliderChange?.(valueToForward);
window.setSettingValue('zoom-factor-setting', valueToForward); await window.setSettingValue('zoom-factor-setting', valueToForward);
window.updateZoomFactor(); window.updateZoomFactor();
forceUpdate(); forceUpdate();
}; };

View file

@ -21,7 +21,7 @@ async function toggleCommunitiesPruning() {
const newValue = !(await window.getOpengroupPruning()); const newValue = !(await window.getOpengroupPruning());
// make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false // make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false
window.setSettingValue(SettingsKey.settingsOpengroupPruning, newValue); await window.setSettingValue(SettingsKey.settingsOpengroupPruning, newValue);
await window.setOpengroupPruning(newValue); await window.setOpengroupPruning(newValue);
ToastUtils.pushRestartNeeded(); ToastUtils.pushRestartNeeded();
} catch (e) { } catch (e) {

View file

@ -37,7 +37,7 @@ async function toggleStartInTray() {
const newValue = !(await window.getStartInTray()); const newValue = !(await window.getStartInTray());
// make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false // make sure to write it here too, as this is the value used on the UI to mark the toggle as true/false
window.setSettingValue(SettingsKey.settingsStartInTray, newValue); await window.setSettingValue(SettingsKey.settingsStartInTray, newValue);
await window.setStartInTray(newValue); await window.setStartInTray(newValue);
if (!newValue) { if (!newValue) {
ToastUtils.pushRestartNeeded(); ToastUtils.pushRestartNeeded();
@ -73,9 +73,9 @@ export const SettingsCategoryPermissions = (props: { hasPassword: boolean | null
active={Boolean(window.getCallMediaPermissions())} active={Boolean(window.getCallMediaPermissions())}
/> />
<SessionToggleWithDescription <SessionToggleWithDescription
onClickToggle={() => { onClickToggle={async () => {
const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate)); const old = Boolean(window.getSettingValue(SettingsKey.settingsAutoUpdate));
window.setSettingValue(SettingsKey.settingsAutoUpdate, !old); await window.setSettingValue(SettingsKey.settingsAutoUpdate, !old);
forceUpdate(); forceUpdate();
}} }}
title={window.i18n('autoUpdateSettingTitle')} title={window.i18n('autoUpdateSettingTitle')}

View file

@ -28,7 +28,7 @@ function displayPasswordModal(
async function toggleLinkPreviews() { async function toggleLinkPreviews() {
const newValue = !window.getSettingValue(SettingsKey.settingsLinkPreview); const newValue = !window.getSettingValue(SettingsKey.settingsLinkPreview);
window.setSettingValue(SettingsKey.settingsLinkPreview, newValue); await window.setSettingValue(SettingsKey.settingsLinkPreview, newValue);
if (!newValue) { if (!newValue) {
await Data.createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: false }); await Data.createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: false });
} else { } else {
@ -63,9 +63,9 @@ export const SettingsCategoryPrivacy = (props: {
return ( return (
<> <>
<SessionToggleWithDescription <SessionToggleWithDescription
onClickToggle={() => { onClickToggle={async () => {
const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt)); const old = Boolean(window.getSettingValue(SettingsKey.settingsReadReceipt));
window.setSettingValue(SettingsKey.settingsReadReceipt, !old); await window.setSettingValue(SettingsKey.settingsReadReceipt, !old);
forceUpdate(); forceUpdate();
}} }}
title={window.i18n('readReceiptSettingTitle')} title={window.i18n('readReceiptSettingTitle')}
@ -73,9 +73,9 @@ export const SettingsCategoryPrivacy = (props: {
active={window.getSettingValue(SettingsKey.settingsReadReceipt)} active={window.getSettingValue(SettingsKey.settingsReadReceipt)}
/> />
<SessionToggleWithDescription <SessionToggleWithDescription
onClickToggle={() => { onClickToggle={async () => {
const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator)); const old = Boolean(window.getSettingValue(SettingsKey.settingsTypingIndicator));
window.setSettingValue(SettingsKey.settingsTypingIndicator, !old); await window.setSettingValue(SettingsKey.settingsTypingIndicator, !old);
forceUpdate(); forceUpdate();
}} }}
title={window.i18n('typingIndicatorsSettingTitle')} title={window.i18n('typingIndicatorsSettingTitle')}

View file

@ -7,6 +7,7 @@ const settingsSpellCheck = 'spell-check';
const settingsLinkPreview = 'link-preview-setting'; const settingsLinkPreview = 'link-preview-setting';
const settingsStartInTray = 'start-in-tray-setting'; const settingsStartInTray = 'start-in-tray-setting';
const settingsOpengroupPruning = 'prune-setting'; const settingsOpengroupPruning = 'prune-setting';
const settingsNotification = 'notification-setting';
export const SettingsKey = { export const SettingsKey = {
settingsReadReceipt, settingsReadReceipt,
@ -17,4 +18,5 @@ export const SettingsKey = {
settingsLinkPreview, settingsLinkPreview,
settingsStartInTray, settingsStartInTray,
settingsOpengroupPruning, settingsOpengroupPruning,
settingsNotification,
}; };

View file

@ -497,8 +497,8 @@ export async function showLinkSharingConfirmationModalDialog(e: any) {
title: window.i18n('linkPreviewsTitle'), title: window.i18n('linkPreviewsTitle'),
message: window.i18n('linkPreviewsConfirmMessage'), message: window.i18n('linkPreviewsConfirmMessage'),
okTheme: SessionButtonColor.Danger, okTheme: SessionButtonColor.Danger,
onClickOk: () => { onClickOk: async () => {
window.setSettingValue('link-preview-setting', true); await window.setSettingValue('link-preview-setting', true);
}, },
onClickClose: async () => { onClickClose: async () => {
await Data.createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: true }); await Data.createOrUpdateItem({ id: hasLinkPreviewPopupBeenDisplayed, value: true });

View file

@ -275,14 +275,6 @@ async function start() {
const prevLaunchCount = window.getSettingValue('launch-count'); const prevLaunchCount = window.getSettingValue('launch-count');
// tslint:disable-next-line: restrict-plus-operands // tslint:disable-next-line: restrict-plus-operands
const launchCount = !prevLaunchCount ? 1 : prevLaunchCount + 1; const launchCount = !prevLaunchCount ? 1 : prevLaunchCount + 1;
window.setSettingValue('launch-count', launchCount);
// On first launch
if (launchCount === 1) {
// Initialise default settings
window.setSettingValue('hide-menu-bar', true);
window.setSettingValue('link-preview-setting', false);
}
window.setTheme = newTheme => { window.setTheme = newTheme => {
window.Events.setThemeSetting(newTheme); window.Events.setThemeSetting(newTheme);
@ -351,6 +343,14 @@ async function start() {
openInbox(); openInbox();
} }
}; };
await window.setSettingValue('launch-count', launchCount);
// On first launch
if (launchCount === 1) {
// Initialise default settings
await window.setSettingValue('hide-menu-bar', true);
await window.setSettingValue('link-preview-setting', false);
}
WhisperEvents.on('openInbox', () => { WhisperEvents.on('openInbox', () => {
openInbox(); openInbox();

View file

@ -22,7 +22,7 @@ export type LocalizerKeys =
| 'timerOption_10_seconds_abbreviated' | 'timerOption_10_seconds_abbreviated'
| 'enterDisplayName' | 'enterDisplayName'
| 'connectToServerFail' | 'connectToServerFail'
| 'disableNotifications' | 'moreInformation'
| 'publicChatExists' | 'publicChatExists'
| 'noMediaUntilApproved' | 'noMediaUntilApproved'
| 'passwordViewTitle' | 'passwordViewTitle'
@ -67,6 +67,7 @@ export type LocalizerKeys =
| 'conversationsSettingsTitle' | 'conversationsSettingsTitle'
| 'tookAScreenshot' | 'tookAScreenshot'
| 'from' | 'from'
| 'requestsSubtitle'
| 'thisMonth' | 'thisMonth'
| 'next' | 'next'
| 'addModerators' | 'addModerators'
@ -85,7 +86,7 @@ export type LocalizerKeys =
| 'windowMenuZoom' | 'windowMenuZoom'
| 'allUsersAreRandomly...' | 'allUsersAreRandomly...'
| 'cameraPermissionNeeded' | 'cameraPermissionNeeded'
| 'requestsSubtitle' | 'notificationsSettingsContent'
| 'ringing' | 'ringing'
| 'closedGroupInviteSuccessTitle' | 'closedGroupInviteSuccessTitle'
| 'accept' | 'accept'
@ -153,7 +154,7 @@ export type LocalizerKeys =
| 'removeAccountPasswordDescription' | 'removeAccountPasswordDescription'
| 'establishingConnection' | 'establishingConnection'
| 'noModeratorsToRemove' | 'noModeratorsToRemove'
| 'moreInformation' | 'youHaveANewFriendRequest'
| 'offline' | 'offline'
| 'appearanceSettingsTitle' | 'appearanceSettingsTitle'
| 'mainMenuView' | 'mainMenuView'
@ -223,6 +224,7 @@ export type LocalizerKeys =
| 'timerOption_10_seconds' | 'timerOption_10_seconds'
| 'helpSettingsTitle' | 'helpSettingsTitle'
| 'openMessageRequestInboxDescription' | 'openMessageRequestInboxDescription'
| 'notificationPreview'
| 'noteToSelf' | 'noteToSelf'
| 'failedToAddAsModerator' | 'failedToAddAsModerator'
| 'disabledDisappearingMessages' | 'disabledDisappearingMessages'
@ -414,7 +416,6 @@ export type LocalizerKeys =
| 'youLeftTheGroup' | 'youLeftTheGroup'
| 'theyChangedTheTimer' | 'theyChangedTheTimer'
| 'userBanned' | 'userBanned'
| 'youHaveANewFriendRequest'
| 'addACaption' | 'addACaption'
| 'timerOption_5_seconds_abbreviated' | 'timerOption_5_seconds_abbreviated'
| 'removeFromModerators' | 'removeFromModerators'

View file

@ -1,4 +1,4 @@
import _ from 'lodash'; import { debounce, last } from 'lodash';
import { getStatus } from '../notifications'; import { getStatus } from '../notifications';
import { UserSetting } from '../notifications/getStatus'; import { UserSetting } from '../notifications/getStatus';
import { isMacOS } from '../OS'; import { isMacOS } from '../OS';
@ -41,7 +41,7 @@ let currentNotifications: Array<SessionNotification> = [];
// to manually close them. This introduces a minimum amount of time between calls, // to manually close them. This introduces a minimum amount of time between calls,
// and batches up the quick successive update() calls we get from an incoming // and batches up the quick successive update() calls we get from an incoming
// read sync, which might have a number of messages referenced inside of it. // read sync, which might have a number of messages referenced inside of it.
const debouncedUpdate = _.debounce(update, 2000); const debouncedUpdate = debounce(update, 2000);
const fastUpdate = update; const fastUpdate = update;
function clear() { function clear() {
@ -156,7 +156,7 @@ function update() {
return; return;
} }
const lastNotification = _.last(currentNotifications); const lastNotification = last(currentNotifications);
if (!lastNotification) { if (!lastNotification) {
return; return;

2
ts/window.d.ts vendored
View file

@ -31,7 +31,7 @@ declare global {
clipboard: any; clipboard: any;
dcodeIO: any; dcodeIO: any;
getSettingValue: (id: string, comparisonValue?: any) => any; getSettingValue: (id: string, comparisonValue?: any) => any;
setSettingValue: (id: string, value: any) => void; setSettingValue: (id: string, value: any) => Promise<void>;
i18n: LocalizerType; i18n: LocalizerType;
log: any; log: any;