[IMPROVE] Rewrite NotificationPreferences to React component (#19672)
Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com> Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>pull/19565/merge
parent
7149b283ef
commit
e94652bcfe
@ -1,58 +0,0 @@ |
||||
.flex-tab { |
||||
& .push-notifications { |
||||
& .input.checkbox.toggle { |
||||
width: 40px; |
||||
} |
||||
|
||||
& ul { |
||||
& li { |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
|
||||
& form { |
||||
& label { |
||||
display: block; |
||||
|
||||
margin-bottom: 5px; |
||||
|
||||
font-weight: bold; |
||||
} |
||||
|
||||
& div span { |
||||
font-size: 14px; |
||||
|
||||
& i.icon-pencil { |
||||
margin-left: 3px; |
||||
|
||||
font-size: 12px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
& .submit { |
||||
margin-top: 30px; |
||||
|
||||
text-align: center; |
||||
} |
||||
|
||||
& [data-edit], |
||||
& [data-play] { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
& .disable-notifications, |
||||
& .unread-room-status { |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
& label { |
||||
flex: 1 1; |
||||
} |
||||
} |
||||
|
||||
& .alert { |
||||
padding: 0.5rem; |
||||
} |
||||
} |
||||
} |
@ -1,179 +0,0 @@ |
||||
<template name="pushNotificationsFlexTab"> |
||||
<main class="rc-user-info__scroll"> |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-switch-double"> |
||||
<div class="rc-switch-double__label {{#if notificationIsEnabled}}disabled{{/if}}"> |
||||
{{_ "Turn_OFF"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Mute_all_notifications"}} |
||||
</div> |
||||
</div> |
||||
<div class="rc-switch rc-switch--blue"> |
||||
<label class="rc-switch__label"> |
||||
<input type="checkbox" class="rc-switch__input js-input-check" value="0" id="disableNotifications" name="disableNotifications" checked="{{$eq notificationIsEnabled true}}"> |
||||
<span class="rc-switch__button"> |
||||
<span class="rc-switch__button-inside"></span> |
||||
</span> |
||||
</label> |
||||
</div> |
||||
<div class="rc-switch-double__label {{#unless notificationIsEnabled}}disabled{{/unless}}"> |
||||
{{_ "Turn_ON"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Receive_alerts"}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-switch-double"> |
||||
<div class="rc-switch-double__label {{#if muteGroupMentions}}disabled{{/if}}"> |
||||
{{_ "Receive_Group_Mentions"}} |
||||
</div> |
||||
<div class="rc-switch rc-switch--blue"> |
||||
<label class="rc-switch__label"> |
||||
<input type="checkbox" class="rc-switch__input js-input-check" id="muteGroupMentions" name="muteGroupMentions" value="1" checked="{{$eq muteGroupMentions true}}"> |
||||
<span class="rc-switch__button"> |
||||
<span class="rc-switch__button-inside"></span> |
||||
</span> |
||||
</label> |
||||
</div> |
||||
<div class="rc-switch-double__label {{#unless muteGroupMentions}}disabled{{/unless}}"> |
||||
{{_ "Mute_Group_Mentions"}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-switch-double"> |
||||
<div class="rc-switch-double__label {{#if showUnreadStatus}}disabled{{/if}}"> |
||||
{{_ "Hide_counter"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Do_not_display_unread_counter"}} |
||||
</div> |
||||
</div> |
||||
<div class="rc-switch rc-switch--blue"> |
||||
<label class="rc-switch__label"> |
||||
<input type="checkbox" class="rc-switch__input js-input-check" id="hideUnreadStatus" name="hideUnreadStatus" value="1" checked="{{$eq showUnreadStatus true}}"> |
||||
<span class="rc-switch__button"> |
||||
<span class="rc-switch__button-inside"></span> |
||||
</span> |
||||
</label> |
||||
</div> |
||||
<div class="rc-switch-double__label {{#unless showUnreadStatus}}disabled{{/unless}}"> |
||||
{{_ "Show_counter"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Display_unread_counter"}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{#if notificationIsEnabled}} |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-user-info__config"> |
||||
<div class="rc-user-info__config-header"> |
||||
{{> icon block="rc-user-info__config-icon" icon="computer"}} |
||||
<span class="rc-user-info__config-label">{{_ "Desktop"}}</span> |
||||
</div> |
||||
<div class="rc-user-info__config-content"> |
||||
<div class="rc-user-info__config-name">{{_ "Alerts"}}:</div> |
||||
{{# with "desktopNotifications"}} |
||||
<div class="rc-user-info__config-value"> |
||||
{{subValue 'desktopNotifications'}} |
||||
{{> icon block="rc-user-info__config-content-icon" icon="arrow-down"}} |
||||
</div> |
||||
{{/with}} |
||||
</div> |
||||
<div class="rc-user-info__config-content"> |
||||
<div class="rc-user-info__config-name">{{_ "Audio"}}:</div> |
||||
{{# with "audioNotifications"}} |
||||
<div class="rc-user-info__config-value"> |
||||
{{subValue 'audioNotifications'}} |
||||
{{> icon block="rc-user-info__config-content-icon" icon="arrow-down"}} |
||||
</div> |
||||
{{/with}} |
||||
</div> |
||||
<div class="rc-user-info__config-content"> |
||||
<div class="rc-user-info__config-name">{{_ "Sound"}}:</div> |
||||
{{# with "audioNotificationValue"}} |
||||
<div class="rc-user-info__config-value"> |
||||
{{audioNotificationValue}} |
||||
{{> icon block="rc-user-info__config-content-icon" icon="arrow-down"}} |
||||
</div> |
||||
<i class="icon-play-circled" data-play="{{audioNotificationValue}}"></i> |
||||
{{/with}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-user-info__config"> |
||||
<div class="rc-user-info__config-header"> |
||||
{{> icon block="rc-user-info__config-icon" icon="mobile"}} |
||||
<span class="rc-user-info__config-label">{{_ "Mobile"}}</span> |
||||
</div> |
||||
<div class="rc-user-info__config-content"> |
||||
<div class="rc-user-info__config-name">{{_ "Alerts"}}:</div> |
||||
{{# with "mobilePushNotifications"}} |
||||
<div class="rc-user-info__config-value"> |
||||
{{subValue "mobilePushNotifications"}} |
||||
{{> icon block="rc-user-info__config-content-icon" icon="arrow-down"}} |
||||
</div> |
||||
{{/with}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-user-info__config"> |
||||
<div class="rc-user-info__config-header"> |
||||
{{> icon block="rc-user-info__config-icon" icon="mail"}} |
||||
<span class="rc-user-info__config-label">{{_ "Email"}}</span> |
||||
</div> |
||||
<div class="rc-user-info__config-content"> |
||||
<div class="rc-user-info__config-name">{{_ "Alerts"}}:</div> |
||||
{{# with "emailNotifications"}} |
||||
<div class="rc-user-info__config-value"> |
||||
{{subValue 'emailNotifications'}} |
||||
{{> icon block="rc-user-info__config-content-icon" icon="arrow-down"}} |
||||
</div> |
||||
{{/with}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{/if}} |
||||
</main> |
||||
<div class="rc-user-info__flex rc-user-info__row"> |
||||
<button class="rc-button js-cancel rc-button--outline" title="{{_ 'Cancel'}}">{{_ 'Cancel'}}</button> |
||||
<button class="rc-button rc-button--primary js-save" title="{{_ 'Save'}}" disabled={{disabled}}>{{_ 'Save'}}</button> |
||||
</div> |
||||
</template> |
||||
<!-- <div class="rc-user-info__row rc-user-info__row--separator"> |
||||
<div class="rc-switch-double"> |
||||
<div class="rc-switch-double__label"> |
||||
{{_ "User_default"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Keep_default_user_settings"}} |
||||
</div> |
||||
</div> |
||||
<div class="rc-switch rc-switch--blue"> |
||||
<label class="rc-switch__label"> |
||||
<input type="checkbox" class="rc-switch__input js-input-check" id="customize" name="customize" value="1" checked="{{$eq customize true}}"> |
||||
<span class="rc-switch__button"> |
||||
<span class="rc-switch__button-inside"></span> |
||||
</span> |
||||
</label> |
||||
</div> |
||||
<div class="rc-switch-double__label"> |
||||
{{_ "Customize"}} |
||||
<div class="rc-switch-double__description"> |
||||
{{_ "Create_unique_rules_for_this_channel"}} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> --> |
||||
|
||||
<template name="pushNotificationsPopover"> |
||||
{{#each options}} |
||||
<div class="rc-popover__item"> |
||||
<input type="radio" class="rc-popover__item-radio" id="{{id}}" name="{{name}}" value="{{value}}" /> |
||||
<label for="{{id}}" class="rc-popover__item-radio-label">{{_ label}}</label> |
||||
</div> |
||||
{{/each}} |
||||
</template> |
@ -1,322 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Session } from 'meteor/session'; |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { settings } from '../../../settings'; |
||||
import { getUserPreference, handleError, t } from '../../../utils'; |
||||
import { popover } from '../../../ui-utils'; |
||||
import { CustomSounds } from '../../../custom-sounds/client'; |
||||
import { ChatSubscription } from '../../../models'; |
||||
|
||||
const notificationLabels = { |
||||
all: 'All_messages', |
||||
mentions: 'Mentions', |
||||
nothing: 'Nothing', |
||||
}; |
||||
|
||||
const getAudioAssetsArray = () => CustomSounds.getList().map((audio) => ({ |
||||
id: `audioNotificationValue${ audio.name }`, |
||||
name: 'audioNotificationValue', |
||||
label: audio.name, |
||||
value: `${ audio._id } ${ audio.name }`, |
||||
})); |
||||
|
||||
const getAudioAssetValue = (value) => { |
||||
const asset = CustomSounds.getList().find((audio) => audio._id === value); |
||||
return asset ? `${ asset._id } ${ asset.name }` : '0 Default'; |
||||
}; |
||||
|
||||
const call = (method, ...params) => new Promise((resolve, reject) => { |
||||
Meteor.call(method, ...params, (err, result) => { |
||||
if (err) { |
||||
handleError(err); |
||||
return reject(err); |
||||
} |
||||
return resolve(result); |
||||
}); |
||||
}); |
||||
|
||||
Template.pushNotificationsFlexTab.helpers({ |
||||
notificationIsEnabled() { |
||||
return !Template.instance().form.disableNotifications.get(); |
||||
}, |
||||
disableNotifications() { |
||||
return Template.instance().form.disableNotifications.get(); |
||||
}, |
||||
showUnreadStatus() { |
||||
return !Template.instance().form.hideUnreadStatus.get(); |
||||
}, |
||||
muteGroupMentions() { |
||||
return Template.instance().form.muteGroupMentions.get(); |
||||
}, |
||||
hideUnreadStatus() { |
||||
return Template.instance().form.hideUnreadStatus.get(); |
||||
}, |
||||
audioNotifications() { |
||||
return Template.instance().form.audioNotifications.get(); |
||||
}, |
||||
audioNotificationValue() { |
||||
const audioNotificationValue = Template.instance().form.audioNotificationValue.get(); |
||||
const value = audioNotificationValue && audioNotificationValue.split(' '); |
||||
if (!value || value[0] === '0') { |
||||
return t('Use_account_preference'); |
||||
} |
||||
|
||||
return value[1]; |
||||
}, |
||||
desktopNotifications() { |
||||
return Template.instance().form.desktopNotifications.get(); |
||||
}, |
||||
mobilePushNotifications() { |
||||
return Template.instance().form.mobilePushNotifications.get(); |
||||
}, |
||||
emailNotifications() { |
||||
return Template.instance().form.emailNotifications.get(); |
||||
}, |
||||
subValue(field) { |
||||
const { form } = Template.instance(); |
||||
if (form[field]) { |
||||
switch (form[field].get()) { |
||||
case 'all': |
||||
return t('All_messages'); |
||||
case 'nothing': |
||||
return t('Nothing'); |
||||
case 'default': |
||||
return t('Use_account_preference'); |
||||
case 'mentions': |
||||
return t('Mentions'); |
||||
default: |
||||
return t('Use_account_preference'); |
||||
} |
||||
} |
||||
}, |
||||
defaultAudioNotification() { |
||||
let preference = getUserPreference(Meteor.userId(), 'audioNotifications'); |
||||
if (preference === 'default') { |
||||
preference = settings.get('Accounts_Default_User_Preferences_audioNotifications'); |
||||
} |
||||
return notificationLabels[preference]; |
||||
}, |
||||
defaultDesktopNotification() { |
||||
let preference = getUserPreference(Meteor.userId(), 'desktopNotifications'); |
||||
if (preference === 'default') { |
||||
preference = settings.get('Accounts_Default_User_Preferences_desktopNotifications'); |
||||
} |
||||
return notificationLabels[preference]; |
||||
}, |
||||
defaultMobileNotification() { |
||||
let preference = getUserPreference(Meteor.userId(), 'mobileNotifications'); |
||||
if (preference === 'default') { |
||||
preference = settings.get('Accounts_Default_User_Preferences_mobileNotifications'); |
||||
} |
||||
return notificationLabels[preference]; |
||||
}, |
||||
disabled() { |
||||
const { original, form } = Template.instance(); |
||||
return Object.keys(original).every((key) => original[key].get() === form[key].get()); |
||||
}, |
||||
}); |
||||
|
||||
Template.pushNotificationsFlexTab.onCreated(function() { |
||||
const rid = Session.get('openedRoom'); |
||||
const sub = ChatSubscription.findOne({ rid }, { |
||||
fields: { |
||||
disableNotifications: 1, |
||||
hideUnreadStatus: 1, |
||||
audioNotifications: 1, |
||||
desktopNotifications: 1, |
||||
mobilePushNotifications: 1, |
||||
emailNotifications: 1, |
||||
audioNotificationValue: 1, |
||||
muteGroupMentions: 1, |
||||
}, |
||||
}) || {}; |
||||
|
||||
const { |
||||
disableNotifications = false, |
||||
hideUnreadStatus = false, |
||||
audioNotifications = 'default', |
||||
desktopNotifications = 'default', |
||||
mobilePushNotifications = 'default', |
||||
emailNotifications = 'default', |
||||
muteGroupMentions = false, |
||||
} = sub; |
||||
|
||||
const audioNotificationValue = sub.audioNotificationValue && getAudioAssetValue(sub.audioNotificationValue); |
||||
|
||||
this.original = { |
||||
disableNotifications: new ReactiveVar(disableNotifications), |
||||
hideUnreadStatus: new ReactiveVar(hideUnreadStatus), |
||||
audioNotifications: new ReactiveVar(audioNotifications), |
||||
desktopNotifications: new ReactiveVar(desktopNotifications), |
||||
mobilePushNotifications: new ReactiveVar(mobilePushNotifications), |
||||
emailNotifications: new ReactiveVar(emailNotifications), |
||||
audioNotificationValue: new ReactiveVar(audioNotificationValue), |
||||
muteGroupMentions: new ReactiveVar(muteGroupMentions), |
||||
}; |
||||
|
||||
this.form = { |
||||
disableNotifications: new ReactiveVar(disableNotifications), |
||||
hideUnreadStatus: new ReactiveVar(hideUnreadStatus), |
||||
audioNotifications: new ReactiveVar(audioNotifications), |
||||
desktopNotifications: new ReactiveVar(desktopNotifications), |
||||
mobilePushNotifications: new ReactiveVar(mobilePushNotifications), |
||||
emailNotifications: new ReactiveVar(emailNotifications), |
||||
audioNotificationValue: new ReactiveVar(audioNotificationValue), |
||||
muteGroupMentions: new ReactiveVar(muteGroupMentions), |
||||
}; |
||||
|
||||
this.saveSetting = async () => { |
||||
Object.keys(this.original).forEach(async (field) => { |
||||
if (this.original[field].get() === this.form[field].get()) { |
||||
return; |
||||
} |
||||
let value = this.form[field].get(); |
||||
|
||||
if (typeof value === 'boolean') { |
||||
value = value ? '1' : '0'; |
||||
} |
||||
const rid = Session.get('openedRoom'); |
||||
switch (field) { |
||||
case 'audioNotificationValue': |
||||
await call('saveAudioNotificationValue', rid, value.split(' ')[0]); |
||||
break; |
||||
default: |
||||
await call('saveNotificationSettings', rid, field, value); |
||||
} |
||||
this.original[field].set(this.form[field].get()); |
||||
}); |
||||
}; |
||||
}); |
||||
|
||||
Template.pushNotificationsFlexTab.events({ |
||||
'click .js-cancel'(e, instance) { |
||||
instance.data.tabBar.close(); |
||||
}, |
||||
|
||||
'click .js-save'(e, instance) { |
||||
e.preventDefault(); |
||||
instance.saveSetting(); |
||||
}, |
||||
|
||||
'click [data-play]'(e) { |
||||
e.preventDefault(); |
||||
|
||||
const uid = Meteor.userId(); |
||||
const formValue = Template.instance().form.audioNotificationValue.get(); |
||||
|
||||
const value = formValue && formValue.split(' ')[0] && formValue.split(' ')[0] !== '0' |
||||
? formValue.split(' ')[0] |
||||
: getUserPreference(uid, 'newMessageNotification'); |
||||
|
||||
if (!value || value === 'none') { |
||||
return; |
||||
} |
||||
|
||||
const audioVolume = getUserPreference(uid, 'notificationsSoundVolume'); |
||||
CustomSounds.play(value, { |
||||
volume: Number((audioVolume / 100).toPrecision(2)), |
||||
}); |
||||
}, |
||||
|
||||
'change input[type=checkbox]'(e, instance) { |
||||
e.preventDefault(); |
||||
const name = $(e.currentTarget).attr('name'); |
||||
const checked = ['disableNotifications', 'hideUnreadStatus'].includes(name) ? !e.currentTarget.checked : e.currentTarget.checked; |
||||
instance.form[name].set(checked); |
||||
}, |
||||
|
||||
'click .rc-user-info__config-value'(e) { |
||||
const instance = Template.instance(); |
||||
const key = this.valueOf(); |
||||
|
||||
let options; |
||||
|
||||
switch (key) { |
||||
case 'audioNotificationValue': |
||||
const audioAssetsArray = getAudioAssetsArray(); |
||||
options = [ |
||||
{ |
||||
id: 'audioNotificationValueNone', |
||||
name: 'audioNotificationValue', |
||||
label: 'None', |
||||
value: 'none None', |
||||
}, |
||||
{ |
||||
id: 'audioNotificationValueDefault', |
||||
name: 'audioNotificationValue', |
||||
label: 'Default', |
||||
value: '0 Default', |
||||
}, |
||||
...audioAssetsArray, |
||||
]; |
||||
break; |
||||
default: |
||||
options = [{ |
||||
id: 'desktopNotificationsDefault', |
||||
name: 'desktopNotifications', |
||||
label: 'Default', |
||||
value: 'default', |
||||
}, |
||||
{ |
||||
id: 'desktopNotificationsAll_messages', |
||||
name: 'desktopNotifications', |
||||
label: 'All_messages', |
||||
value: 'all', |
||||
}, |
||||
{ |
||||
id: 'desktopNotificationsMentions', |
||||
name: 'desktopNotifications', |
||||
label: 'Mentions', |
||||
value: 'mentions', |
||||
}, |
||||
{ |
||||
id: 'desktopNotificationsNothing', |
||||
name: 'desktopNotifications', |
||||
label: 'Nothing', |
||||
value: 'nothing', |
||||
}]; |
||||
} |
||||
|
||||
const config = { |
||||
popoverClass: 'notifications-preferences', |
||||
template: 'pushNotificationsPopover', |
||||
data: { |
||||
change: (value) => instance.form[key].set(value), |
||||
value: instance.form[key].get(), |
||||
options, |
||||
}, |
||||
currentTarget: e.currentTarget, |
||||
offsetVertical: e.currentTarget.clientHeight + 10, |
||||
}; |
||||
popover.open(config); |
||||
}, |
||||
}); |
||||
|
||||
|
||||
Template.pushNotificationsPopover.onCreated(function() { |
||||
this.change = this.data.change; |
||||
}); |
||||
|
||||
Template.pushNotificationsPopover.onRendered(function() { |
||||
this.find(`[value='${ this.data.value }']`).checked = true; |
||||
}); |
||||
|
||||
Template.pushNotificationsPopover.helpers({ |
||||
options() { |
||||
return Template.instance().data.options; |
||||
}, |
||||
defaultDesktopNotification() { |
||||
let preference = getUserPreference(Meteor.userId(), 'desktopNotifications'); |
||||
if (preference === 'default') { |
||||
preference = settings.get('Accounts_Default_User_Preferences_desktopNotifications'); |
||||
} |
||||
return notificationLabels[preference]; |
||||
}, |
||||
}); |
||||
Template.pushNotificationsPopover.events({ |
||||
'change input'(e, instance) { |
||||
instance.change && instance.change(e.target.value); |
||||
}, |
||||
}); |
@ -0,0 +1,143 @@ |
||||
import React from 'react'; |
||||
import { Button, ButtonGroup, FieldGroup, Icon } from '@rocket.chat/fuselage'; |
||||
import { useMutableCallback } from '@rocket.chat/fuselage-hooks'; |
||||
|
||||
import { useForm } from '../../hooks/useForm'; |
||||
import { useUserSubscription, useUser } from '../../contexts/UserContext'; |
||||
import { useTranslation } from '../../contexts/TranslationContext'; |
||||
import { useCustomSound } from '../../contexts/CustomSoundContext'; |
||||
import { useEndpointActionExperimental } from '../../hooks/useEndpointAction'; |
||||
import VerticalBar from '../../components/basic/VerticalBar'; |
||||
import { Preferences } from './components/Preferences'; |
||||
import { NotificationByDevice } from './components/NotificationByDevice'; |
||||
import { NotificationToogle } from './components/NotificationToogle'; |
||||
|
||||
|
||||
export const NotificationPreferences = ({ |
||||
handleClose, |
||||
formValues, |
||||
formHandlers, |
||||
formHasUnsavedChanges, |
||||
handlePlaySound, |
||||
handleOptions, |
||||
handleSaveButton, |
||||
handleCancelButton, |
||||
}) => { |
||||
const t = useTranslation(); |
||||
return <> |
||||
<VerticalBar.Header> |
||||
<VerticalBar.Icon name='bell'/> |
||||
<VerticalBar.Text>{t('Notifications_Preferences')}</VerticalBar.Text> |
||||
{handleClose && <VerticalBar.Close onClick={handleClose}/>} |
||||
</VerticalBar.Header> |
||||
<VerticalBar.ScrollableContent> |
||||
<NotificationToogle label={t('Turn_ON')} description={t('Receive_alerts')} onChange={formHandlers.handleTurnOn} defaultChecked={formValues.turnOn}/> |
||||
<NotificationToogle label={t('Mute_Group_Mentions')} onChange={formHandlers.handleMuteGroupMentions} defaultChecked={formValues.muteGroupMentions}/> |
||||
<NotificationToogle label={t('Show_counter')} description={t('Display_unread_counter')} onChange={formHandlers.handleShowCounter} defaultChecked={formValues.showCounter} /> |
||||
<FieldGroup> |
||||
<NotificationByDevice device={t('Desktop')} icon={'computer'}> |
||||
<Preferences id={'DesktopAlert'} onChange={formHandlers.handleDesktopAlert} name={t('Alerts')} options={handleOptions.alerts} optionDefault={formValues.desktopAlert} /> |
||||
<Preferences id={'DesktopAudio'} onChange={formHandlers.handleDesktopAudio} name={t('Audio')} options={handleOptions.audio} optionDefault={formValues.desktopAudio} /> |
||||
<Preferences id={'DesktopSound'} onChange={formHandlers.handleDesktopSound} name={t('Sound')} options={handleOptions.sound} optionDefault={formValues.desktopSound}> |
||||
<Button mis='x4' square ghost onClick={handlePlaySound}> |
||||
<Icon name='play' size='x18' /> |
||||
</Button> |
||||
</Preferences> |
||||
</NotificationByDevice> |
||||
<NotificationByDevice device={t('Mobile')} icon={'mobile'}> |
||||
<Preferences id={'MobileAlert'} onChange={formHandlers.handleMobileAlert} name={t('Alerts')} options={handleOptions.alerts} optionDefault={formValues.mobileAlert} /> |
||||
</NotificationByDevice> |
||||
<NotificationByDevice device={t('Email')} icon={'mail'}> |
||||
<Preferences id={'EmailAlert'} onChange={formHandlers.handleEmailAlert} name={t('Alerts')} options={handleOptions.alerts} optionDefault={formValues.emailAlert} /> |
||||
</NotificationByDevice> |
||||
</FieldGroup> |
||||
</VerticalBar.ScrollableContent> |
||||
<VerticalBar.Footer> |
||||
<ButtonGroup stretch> |
||||
<Button onClick={handleCancelButton}>{t('Cancel')}</Button> |
||||
<Button primary disabled={!formHasUnsavedChanges} onClick={handleSaveButton}>{t('Save')}</Button> |
||||
</ButtonGroup> |
||||
</VerticalBar.Footer> |
||||
</>; |
||||
}; |
||||
|
||||
export default React.memo(({ tabBar, rid }) => { |
||||
const t = useTranslation(); |
||||
|
||||
const subscription = useUserSubscription(rid); |
||||
const userSettingsPreferences = useUser().settings.preferences; |
||||
|
||||
const customSound = useCustomSound(); |
||||
|
||||
const handleClose = useMutableCallback(() => tabBar && tabBar.close()); |
||||
const saveSettings = useEndpointActionExperimental('POST', 'rooms.saveNotification'); |
||||
|
||||
const { values, handlers, hasUnsavedChanges, commit, reset } = useForm( |
||||
{ |
||||
turnOn: !subscription.disableNotifications, |
||||
muteGroupMentions: subscription.muteGroupMentions, |
||||
showCounter: !subscription.hideUnreadStatus, |
||||
desktopAlert: subscription.desktopNotifications || userSettingsPreferences.desktopNotifications, |
||||
desktopAudio: subscription.audioNotifications || userSettingsPreferences.audioNotifications, |
||||
desktopSound: subscription.audioNotificationValue || userSettingsPreferences.newMessageNotification, |
||||
mobileAlert: subscription.mobilePushNotifications || userSettingsPreferences.mobileNotifications, |
||||
emailAlert: subscription.emailNotifications || userSettingsPreferences.emailNotificationMode, |
||||
}, |
||||
); |
||||
|
||||
|
||||
const defaultOption = [ |
||||
['default', t('Default')], |
||||
['all', t('All_messages')], |
||||
['mentions', t('Mentions')], |
||||
['nothing', t('Nothing')], |
||||
]; |
||||
|
||||
const customSoundAsset = Object.entries(customSound.list.get()).map((value) => [value[0], value[1].name]); |
||||
|
||||
const handleOptions = { |
||||
alerts: defaultOption, |
||||
audio: defaultOption, |
||||
sound: [ |
||||
['none None', t('None')], |
||||
['0 default', t('Default')], |
||||
...customSoundAsset, |
||||
], |
||||
}; |
||||
|
||||
const handlePlaySound = () => customSound.play(values.desktopSound); |
||||
|
||||
const handleSaveButton = useMutableCallback(() => { |
||||
const notifications = {}; |
||||
|
||||
notifications.disableNotifications = values.turnOn ? '0' : '1'; |
||||
notifications.muteGroupMentions = values.muteGroupMentions ? '1' : '0'; |
||||
notifications.hideUnreadStatus = values.showCounter ? '0' : '1'; |
||||
notifications.desktopNotifications = values.desktopAlert; |
||||
notifications.audioNotifications = values.desktopAudio; |
||||
notifications.audioNotificationValue = values.desktopSound; |
||||
notifications.mobilePushNotifications = values.mobileAlert; |
||||
notifications.emailNotifications = values.emailAlert; |
||||
|
||||
saveSettings({ |
||||
roomId: rid, |
||||
notifications, |
||||
}); |
||||
|
||||
commit(); |
||||
}); |
||||
|
||||
|
||||
return ( |
||||
<NotificationPreferences |
||||
handleClose={handleClose} |
||||
formValues={values} |
||||
formHandlers={handlers} |
||||
formHasUnsavedChanges={hasUnsavedChanges} |
||||
handlePlaySound={handlePlaySound} |
||||
handleOptions={handleOptions} |
||||
handleSaveButton={handleSaveButton} |
||||
handleCancelButton={reset} |
||||
/> |
||||
); |
||||
}); |
@ -0,0 +1,68 @@ |
||||
import React from 'react'; |
||||
import { Box } from '@rocket.chat/fuselage'; |
||||
|
||||
import VerticalBar from '../../components/basic/VerticalBar'; |
||||
|
||||
import { NotificationsPreferences } from '.'; |
||||
|
||||
export default { |
||||
title: 'components/basic/NotificationsPreferences', |
||||
component: NotificationsPreferences, |
||||
}; |
||||
|
||||
const handleOn = { |
||||
turnOn: true, |
||||
muteGroupMentions: false, |
||||
showCounter: true, |
||||
}; |
||||
|
||||
const handleSwitch = { |
||||
turnOn: () => {}, |
||||
muteGroupMentions: () => {}, |
||||
showCounter: () => {}, |
||||
}; |
||||
|
||||
const defaultOption = [ |
||||
['default', 'Default'], |
||||
['all', 'All_messages'], |
||||
['mentions', 'Mentions'], |
||||
['nothing', 'Nothing'], |
||||
]; |
||||
|
||||
const handleOptions = { |
||||
alerts: defaultOption, |
||||
audio: defaultOption, |
||||
sound: [ |
||||
['none None', 'None'], |
||||
['0 default', 'Default'], |
||||
['chime', 'Chime'], |
||||
], |
||||
}; |
||||
|
||||
const handleSelect = { desktop: {}, mobile: {}, email: {} }; |
||||
|
||||
handleSelect.desktop.alert = 'default'; |
||||
handleSelect.desktop.audio = 'default'; |
||||
handleSelect.desktop.sound = 'chime'; |
||||
|
||||
handleSelect.mobile.alert = 'mentions'; |
||||
|
||||
handleSelect.email.alert = 'nothing'; |
||||
|
||||
export const Default = () => <Box height='600px'> |
||||
<VerticalBar> |
||||
<NotificationsPreferences |
||||
handleOn={handleOn} |
||||
handleSwitch={handleSwitch} |
||||
handleOptions={handleOptions} |
||||
handleSelect={handleSelect} |
||||
handleChangeOption={{ |
||||
desktopAlert: () => {}, |
||||
desktopAudio: () => {}, |
||||
mobileAlert: () => {}, |
||||
emailAlert: () => {}, |
||||
}} |
||||
handleSoundChange={{ desktopSound: () => {} }} |
||||
/> |
||||
</VerticalBar> |
||||
</Box>; |
@ -0,0 +1,13 @@ |
||||
import React from 'react'; |
||||
import { Box, Accordion, Icon, FieldGroup } from '@rocket.chat/fuselage'; |
||||
|
||||
export const NotificationByDevice = React.memo(({ device, icon, children }) => ( |
||||
<Accordion.Item title={<Box display='flex' alignItems='center'> |
||||
<Icon name={icon} size='x18' /> |
||||
<Box fontScale='p2' mi='x16'>{device}</Box> |
||||
</Box>}> |
||||
<FieldGroup> |
||||
{children} |
||||
</FieldGroup> |
||||
</Accordion.Item> |
||||
)); |
@ -0,0 +1,17 @@ |
||||
import React from 'react'; |
||||
import { Box, Field, FieldGroup, ToggleSwitch } from '@rocket.chat/fuselage'; |
||||
import { useUniqueId } from '@rocket.chat/fuselage-hooks'; |
||||
|
||||
export const NotificationToogle = React.memo(({ label, description, onChange, defaultChecked }) => { |
||||
const id = useUniqueId(); |
||||
|
||||
return <FieldGroup> |
||||
<Box display='flex' justifyContent='space-between' alignItems='start'> |
||||
<Box display='flex' flexDirection='column'> |
||||
<Field.Label for={id}>{label}</Field.Label> |
||||
<Field.Description>{description}</Field.Description> |
||||
</Box> |
||||
<ToggleSwitch id={id} onChange={onChange} defaultChecked={defaultChecked} /> |
||||
</Box> |
||||
</FieldGroup>; |
||||
}); |
@ -0,0 +1,14 @@ |
||||
import React from 'react'; |
||||
import { Field, Select } from '@rocket.chat/fuselage'; |
||||
|
||||
export const Preferences = ({ name, options, onChange, optionDefault, children, ...props }) => ( |
||||
<Field {...props}> |
||||
<Field.Label> |
||||
{name} |
||||
</Field.Label> |
||||
<Field.Row> |
||||
<Select onChange={onChange} options={options} value={optionDefault} /> |
||||
{children} |
||||
</Field.Row> |
||||
</Field> |
||||
); |
@ -0,0 +1,3 @@ |
||||
import NotificationPreferences from './NotificationPreferences'; |
||||
|
||||
export default NotificationPreferences; |
Loading…
Reference in new issue