mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[MM-60218] Resettting to default doesnt reset to user's global notification setting in a channel's setting (#28046)
This commit is contained in:
parent
bb4d7de2b5
commit
4c6ac0a432
@ -142,82 +142,97 @@ describe('CRT Desktop notifications', () => {
|
|||||||
|
|
||||||
it('MM-T4417_2 Click on sameMobileSettingsDesktop and check if additional settings still appears', () => {
|
it('MM-T4417_2 Click on sameMobileSettingsDesktop and check if additional settings still appears', () => {
|
||||||
cy.visit(testChannelUrl);
|
cy.visit(testChannelUrl);
|
||||||
|
|
||||||
|
// # Open channel's notification preferences
|
||||||
cy.uiOpenChannelMenu('Notification Preferences');
|
cy.uiOpenChannelMenu('Notification Preferences');
|
||||||
|
|
||||||
cy.get('#desktopNotification-mention').scrollIntoView().should('be.visible').click().then(() => {
|
// * As per previous conditions the mobile and desktop settings should be the same
|
||||||
cy.get('[data-testid="desktopReplyThreads"]').scrollIntoView().should('be.visible').click();
|
cy.get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().should('be.checked');
|
||||||
});
|
|
||||||
cy.get('.channel-notifications-settings-modal__body').scrollTo('center').get('[data-testid="desktopReplyThreads"]').should('be.visible').click();
|
// * Verify that Notify me about section of mobile settings is not visible
|
||||||
cy.get('.channel-notifications-settings-modal__body').get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().click().should('be.checked').then(() => {
|
cy.get('[data-testid="mobile-notify-me-radio-section"]').should('not.exist');
|
||||||
cy.findByText('Notify me about…').should('not.be.visible');
|
|
||||||
|
// # Now uncheck the sameMobileSettingsDesktop so that mobile and desktop settings are different
|
||||||
|
cy.get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().should('be.visible').click();
|
||||||
|
|
||||||
|
// * Verify that Notify me about section of mobile settings is visible
|
||||||
|
cy.get('[data-testid="mobile-notify-me-radio-section"]').should('be.visible').scrollIntoView().within(() => {
|
||||||
|
cy.findByText('Notify me about…').should('be.visible');
|
||||||
|
|
||||||
|
// # Click on mentions option
|
||||||
|
cy.get('[data-testid="MobileNotification-mention"]').should('be.visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
// check the box to see if the additional settings appears
|
// * Verify that Thread reply notifications section of mobile settings is visible
|
||||||
cy.get('.channel-notifications-settings-modal__body').get('[data-testid="sameMobileSettingsDesktop"]').scrollIntoView().click();
|
cy.get('[data-testid="mobile-reply-threads-checkbox-section"]').should('be.visible').scrollIntoView().within(() => {
|
||||||
cy.get('.mm-modal-generic-section-item__title').should('be.visible').and('contain', 'Notify me about');
|
cy.findByText('Notify me about replies to threads I’m following').should('be.visible');
|
||||||
|
|
||||||
cy.get('#MobileNotification-all').should('be.visible').click();
|
|
||||||
cy.get('#MobileNotification-mention').should('be.visible').click().then(() => {
|
|
||||||
cy.get('[data-testid="mobileReplyThreads"]').should('be.visible').click();
|
|
||||||
});
|
});
|
||||||
cy.get('#MobileNotification-none').should('be.visible').click();
|
|
||||||
|
|
||||||
cy.get('[data-testid="autoFollowThreads"]').should('be.visible').click();
|
// # Close the modal
|
||||||
|
cy.get('body').type('{esc}');
|
||||||
// # Save the changes
|
|
||||||
cy.findByText('Save').should('be.visible').click();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('MM-T4417_3 Trigger notifications only on mention replies when channel setting is unchecked', () => {
|
it('MM-T4417_3 Trigger notifications only on mention replies when channel setting is unchecked', () => {
|
||||||
|
// # Visit the test channel
|
||||||
cy.visit(testChannelUrl);
|
cy.visit(testChannelUrl);
|
||||||
|
|
||||||
// Setup notification spy
|
// # Setup notification spy
|
||||||
spyNotificationAs('notifySpy', 'granted');
|
spyNotificationAs('notifySpy1', 'granted');
|
||||||
|
|
||||||
|
// # Open channel's notification preferences for test channel
|
||||||
cy.uiOpenChannelMenu('Notification Preferences');
|
cy.uiOpenChannelMenu('Notification Preferences');
|
||||||
|
|
||||||
|
// # Select "Mentions, direct messages, and keywords only" as notify me about option
|
||||||
cy.get('#desktopNotification-mention').scrollIntoView().should('be.visible').click();
|
cy.get('#desktopNotification-mention').scrollIntoView().should('be.visible').click();
|
||||||
|
|
||||||
|
// # Unselect "Notify me about replies to threads I’m following"
|
||||||
|
cy.get('[data-testid="desktopReplyThreads"]').scrollIntoView().should('be.visible').then(($el) => {
|
||||||
|
if ($el.is(':checked')) {
|
||||||
|
cy.wrap($el).click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// # Select notification checkbox active
|
||||||
|
cy.get('[data-testid="desktopNotificationSoundsCheckbox"]').scrollIntoView().should('be.visible').then(($el) => {
|
||||||
|
if (!$el.is(':checked')) {
|
||||||
|
cy.wrap($el).click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// # Select a notification sound from dropdown
|
||||||
|
cy.get('#desktopNotificationSoundsSelect').scrollIntoView().should('be.visible').click();
|
||||||
|
cy.findByText('Crackle').should('be.visible').click();
|
||||||
|
|
||||||
// # Save the changes
|
// # Save the changes
|
||||||
cy.findByText('Save').should('be.visible').click();
|
cy.findByText('Save').should('be.visible').click();
|
||||||
|
|
||||||
// # Post a root message as other user
|
// # Go to the town-square channel
|
||||||
cy.postMessageAs({sender, message: 'This is a not followed root message', channelId: testChannelId, rootId: ''}).then(({id: postId}) => {
|
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||||
// # Switch to town-square so that unread notifications in test channel may be triggered
|
|
||||||
cy.uiClickSidebarItem('town-square');
|
|
||||||
|
|
||||||
// # Post a message in unfollowed thread as another user
|
// # Post a root message as other user in the test channel
|
||||||
cy.postMessageAs({sender, message: 'This is a reply to the unfollowed thread', channelId: testChannelId, rootId: postId});
|
cy.postMessageAs({sender, message: 'This is the root message which will not have a at-mention in thread', channelId: testChannelId, rootId: ''}).then(({id: postId}) => {
|
||||||
|
// # Post a message in the thread without at-mention
|
||||||
|
cy.postMessageAs({sender, message: 'Reply without at-mention', channelId: testChannelId, rootId: postId}).then(() => {
|
||||||
|
// * Verify Notification stub was not called for threads which does not have at-mention as per channel settings
|
||||||
|
cy.get('@notifySpy1').should('not.be.called');
|
||||||
|
});
|
||||||
|
|
||||||
// * Verify stub was not called for unfollowed thread
|
// # Cleanup
|
||||||
cy.get('@notifySpy').should('not.be.called');
|
cy.apiDeletePost(postId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// # Visit channel
|
// Setup another notification spy
|
||||||
cy.visit(testChannelUrl);
|
spyNotificationAs('notifySpy2', 'granted');
|
||||||
|
|
||||||
// Setup notification spy
|
// # Post another message in the test channel
|
||||||
spyNotificationAs('notifySpy', 'granted');
|
cy.postMessageAs({sender, message: 'This is another root message which will have a at-mention in thread', channelId: testChannelId, rootId: ''}).then(({id: postId}) => {
|
||||||
|
const message = `Reply with at-mention @${receiver.username}`;
|
||||||
// # Post a message
|
|
||||||
cy.postMessage('Hi there, this is a root message');
|
|
||||||
|
|
||||||
// # Get post id of message
|
|
||||||
cy.getLastPostId().then((postId) => {
|
|
||||||
// # Switch to town-square so that unread notifications in test channel may be triggered
|
|
||||||
cy.uiClickSidebarItem('town-square');
|
|
||||||
|
|
||||||
// # Post a message in original thread as another user
|
|
||||||
cy.postMessageAs({sender, message: 'This is a reply to the root post', channelId: testChannelId, rootId: postId});
|
|
||||||
|
|
||||||
// * Verify stub was not called
|
|
||||||
cy.get('@notifySpy').should('not.be.called');
|
|
||||||
|
|
||||||
// # Post a mention message in original thread as another user
|
|
||||||
const message = `@${receiver.username} this is a mention to receiver`;
|
|
||||||
|
|
||||||
|
// # Post a message in the thread with at-mention
|
||||||
cy.postMessageAs({sender, message, channelId: testChannelId, rootId: postId});
|
cy.postMessageAs({sender, message, channelId: testChannelId, rootId: postId});
|
||||||
|
|
||||||
// * Verify stub was called with correct title and body
|
// * Verify Notification stub was called with correct title and body with at-mention as per channel settings
|
||||||
cy.get('@notifySpy').should('have.been.calledWithMatch', `Reply in ${testChannelName}`, (args) => {
|
cy.get('@notifySpy2').should('have.been.calledWithMatch', `Reply in ${testChannelName}`, (args) => {
|
||||||
expect(args.body, `Notification body: "${args.body}" should match: "${message}"`).to.equal(`@${sender.username}: ${message}`);
|
expect(args.body, `Notification body: "${args.body}" should match: "${message}"`).to.equal(`@${sender.username}: ${message}`);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -18,11 +18,11 @@ import {getChannelURL, getPermalinkURL} from 'selectors/urls';
|
|||||||
import {isThreadOpen} from 'selectors/views/threads';
|
import {isThreadOpen} from 'selectors/views/threads';
|
||||||
|
|
||||||
import {getHistory} from 'utils/browser_history';
|
import {getHistory} from 'utils/browser_history';
|
||||||
import Constants, {NotificationLevels, UserStatuses, IgnoreChannelMentions} from 'utils/constants';
|
import Constants, {NotificationLevels, UserStatuses, IgnoreChannelMentions, DesktopSound} from 'utils/constants';
|
||||||
import DesktopApp from 'utils/desktop_api';
|
import DesktopApp from 'utils/desktop_api';
|
||||||
import {stripMarkdown, formatWithRenderer} from 'utils/markdown';
|
import {stripMarkdown, formatWithRenderer} from 'utils/markdown';
|
||||||
import MentionableRenderer from 'utils/markdown/mentionable_renderer';
|
import MentionableRenderer from 'utils/markdown/mentionable_renderer';
|
||||||
import * as NotificationSounds from 'utils/notification_sounds';
|
import {DesktopNotificationSounds, ding} from 'utils/notification_sounds';
|
||||||
import {showNotification} from 'utils/notifications';
|
import {showNotification} from 'utils/notifications';
|
||||||
import {cjkrPattern, escapeRegex} from 'utils/text_formatting';
|
import {cjkrPattern, escapeRegex} from 'utils/text_formatting';
|
||||||
import {isDesktopApp, isMobileApp} from 'utils/user_agent';
|
import {isDesktopApp, isMobileApp} from 'utils/user_agent';
|
||||||
@ -30,21 +30,52 @@ import * as Utils from 'utils/utils';
|
|||||||
|
|
||||||
import {runDesktopNotificationHooks} from './hooks';
|
import {runDesktopNotificationHooks} from './hooks';
|
||||||
|
|
||||||
const getSoundFromChannelMemberAndUser = (member, user) => {
|
/**
|
||||||
if (member?.notify_props?.desktop_sound) {
|
* This function is used to determine if the desktop sound is enabled.
|
||||||
return member.notify_props.desktop_sound === 'on';
|
* It checks if desktop sound is defined in the channel member and if not, it checks if it's defined in the user preferences.
|
||||||
|
*/
|
||||||
|
export function isDesktopSoundEnabled(channelMember, user) {
|
||||||
|
const soundInChannelMemberNotifyProps = channelMember?.notify_props?.desktop_sound;
|
||||||
|
const soundInUserNotifyProps = user?.notify_props?.desktop_sound;
|
||||||
|
|
||||||
|
if (soundInChannelMemberNotifyProps === DesktopSound.ON) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !user.notify_props || user.notify_props.desktop_sound === 'true';
|
if (soundInChannelMemberNotifyProps === DesktopSound.OFF) {
|
||||||
};
|
return false;
|
||||||
|
|
||||||
const getNotificationSoundFromChannelMemberAndUser = (member, user) => {
|
|
||||||
if (member?.notify_props?.desktop_notification_sound) {
|
|
||||||
return member.notify_props.desktop_notification_sound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return user.notify_props?.desktop_notification_sound ? user.notify_props.desktop_notification_sound : 'Bing';
|
if (soundInChannelMemberNotifyProps === DesktopSound.DEFAULT) {
|
||||||
};
|
return soundInUserNotifyProps ? soundInUserNotifyProps === 'true' : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soundInUserNotifyProps) {
|
||||||
|
return soundInUserNotifyProps === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the desktop notification sound from the channel member and user.
|
||||||
|
* It checks if desktop notification sound is defined in the channel member and if not, it checks if it's defined in the user preferences.
|
||||||
|
* If neither is defined, it returns the default sound 'BING'.
|
||||||
|
*/
|
||||||
|
export function getDesktopNotificationSound(channelMember, user) {
|
||||||
|
const notificationSoundInChannelMember = channelMember?.notify_props?.desktop_notification_sound;
|
||||||
|
const notificationSoundInUser = user?.notify_props?.desktop_notification_sound;
|
||||||
|
|
||||||
|
if (notificationSoundInChannelMember && notificationSoundInChannelMember !== DesktopNotificationSounds.DEFAULT) {
|
||||||
|
return notificationSoundInChannelMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationSoundInUser && notificationSoundInUser !== DesktopNotificationSounds.DEFAULT) {
|
||||||
|
return notificationSoundInUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DesktopNotificationSounds.BING;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {import('mattermost-redux/types/actions').ThunkActionFunc<Promise<import('utils/notifications').NotificationResult>, GlobalState>}
|
* @returns {import('mattermost-redux/types/actions').ThunkActionFunc<Promise<import('utils/notifications').NotificationResult>, GlobalState>}
|
||||||
@ -259,7 +290,7 @@ export function sendDesktopNotification(post, msgProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Play a sound if explicitly set in settings
|
//Play a sound if explicitly set in settings
|
||||||
const sound = getSoundFromChannelMemberAndUser(member, user);
|
const desktopSoundEnabled = isDesktopSoundEnabled(member, user);
|
||||||
|
|
||||||
// Notify if you're not looking in the right channel or when
|
// Notify if you're not looking in the right channel or when
|
||||||
// the window itself is not active
|
// the window itself is not active
|
||||||
@ -285,7 +316,7 @@ export function sendDesktopNotification(post, msgProps) {
|
|||||||
notify = true;
|
notify = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let soundName = getNotificationSoundFromChannelMemberAndUser(member, user);
|
let soundName = getDesktopNotificationSound(member, user);
|
||||||
|
|
||||||
const updatedState = getState();
|
const updatedState = getState();
|
||||||
let url = getChannelURL(updatedState, channel, teamId);
|
let url = getChannelURL(updatedState, channel, teamId);
|
||||||
@ -295,7 +326,7 @@ export function sendDesktopNotification(post, msgProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allow plugins to change the notification, or re-enable a notification
|
// Allow plugins to change the notification, or re-enable a notification
|
||||||
const args = {title, body, silent: !sound, soundName, url, notify};
|
const args = {title, body, silent: !desktopSoundEnabled, soundName, url, notify};
|
||||||
const hookResult = await dispatch(runDesktopNotificationHooks(post, msgProps, channel, teamId, args));
|
const hookResult = await dispatch(runDesktopNotificationHooks(post, msgProps, channel, teamId, args));
|
||||||
if (hookResult.error) {
|
if (hookResult.error) {
|
||||||
dispatch(logError(hookResult.error));
|
dispatch(logError(hookResult.error));
|
||||||
@ -309,8 +340,8 @@ export function sendDesktopNotification(post, msgProps) {
|
|||||||
const result = dispatch(notifyMe(title, body, channel, teamId, silent, soundName, url));
|
const result = dispatch(notifyMe(title, body, channel, teamId, silent, soundName, url));
|
||||||
|
|
||||||
//Don't add extra sounds on native desktop clients
|
//Don't add extra sounds on native desktop clients
|
||||||
if (sound && !isDesktopApp() && !isMobileApp()) {
|
if (desktopSoundEnabled && !isDesktopApp() && !isMobileApp()) {
|
||||||
NotificationSounds.ding(soundName);
|
ding(soundName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -7,7 +7,7 @@ import Constants, {NotificationLevels, UserStatuses} from 'utils/constants';
|
|||||||
import * as NotificationSounds from 'utils/notification_sounds';
|
import * as NotificationSounds from 'utils/notification_sounds';
|
||||||
import * as utils from 'utils/notifications';
|
import * as utils from 'utils/notifications';
|
||||||
|
|
||||||
import {sendDesktopNotification} from './notification_actions';
|
import {sendDesktopNotification, isDesktopSoundEnabled, getDesktopNotificationSound} from './notification_actions';
|
||||||
|
|
||||||
describe('notification_actions', () => {
|
describe('notification_actions', () => {
|
||||||
describe('sendDesktopNotification', () => {
|
describe('sendDesktopNotification', () => {
|
||||||
@ -195,7 +195,7 @@ describe('notification_actions', () => {
|
|||||||
expect(spy).toHaveBeenCalledWith({
|
expect(spy).toHaveBeenCalledWith({
|
||||||
body: '@username: Where is Jessica Hyde?',
|
body: '@username: Where is Jessica Hyde?',
|
||||||
requireInteraction: false,
|
requireInteraction: false,
|
||||||
silent: true,
|
silent: false,
|
||||||
title: 'Utopia',
|
title: 'Utopia',
|
||||||
onClick: expect.any(Function),
|
onClick: expect.any(Function),
|
||||||
});
|
});
|
||||||
@ -415,7 +415,7 @@ describe('notification_actions', () => {
|
|||||||
expect(spy).toHaveBeenCalledWith({
|
expect(spy).toHaveBeenCalledWith({
|
||||||
body: '@username: Where is Jessica Hyde?',
|
body: '@username: Where is Jessica Hyde?',
|
||||||
requireInteraction: false,
|
requireInteraction: false,
|
||||||
silent: true,
|
silent: false,
|
||||||
title: 'Reply in Utopia',
|
title: 'Reply in Utopia',
|
||||||
onClick: expect.any(Function),
|
onClick: expect.any(Function),
|
||||||
});
|
});
|
||||||
@ -509,3 +509,163 @@ describe('notification_actions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isDesktopSoundEnabled', () => {
|
||||||
|
test('should return channel member sound if it exists', () => {
|
||||||
|
const channelMember1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'on',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember1, user1)).toBe(true);
|
||||||
|
|
||||||
|
const channelMember2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'off',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember2, user2)).toBe(false);
|
||||||
|
|
||||||
|
const channelMember3 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'default',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user3 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember3, user3)).toBe(false);
|
||||||
|
|
||||||
|
const channelMember4 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'default',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user4 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'true',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember4, user4)).toBe(true);
|
||||||
|
|
||||||
|
const channelMember5 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'on',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user5 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember5, user5)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return user sound if channel member sound is not defined', () => {
|
||||||
|
const channelMember1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'true',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember1, user1)).toBe(true);
|
||||||
|
|
||||||
|
const channelMember2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember2, user2)).toBe(false);
|
||||||
|
|
||||||
|
const channelMember3 = {
|
||||||
|
notify_props: {},
|
||||||
|
};
|
||||||
|
const user3 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember3, user3)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return default if both channel member and user are not defined', () => {
|
||||||
|
const channelMember = {};
|
||||||
|
const user = {};
|
||||||
|
expect(isDesktopSoundEnabled(channelMember, user)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getDesktopNotificationSound', () => {
|
||||||
|
test('should return channel member notification sound if it exists', () => {
|
||||||
|
const channelMember1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Crackle',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(getDesktopNotificationSound(channelMember1, user1)).toBe('Crackle');
|
||||||
|
|
||||||
|
const channelMember2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user2 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(getDesktopNotificationSound(channelMember2, user2)).toBe('Bing');
|
||||||
|
|
||||||
|
const channelMember3 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Crackle',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const user3 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(getDesktopNotificationSound(channelMember3, user3)).toBe('Crackle');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return user notification sound if channel member sound is not defined', () => {
|
||||||
|
const channelMember1 = {};
|
||||||
|
const user1 = {
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Crackle',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(getDesktopNotificationSound(channelMember1, user1)).toBe('Crackle');
|
||||||
|
|
||||||
|
const channelMember2 = {};
|
||||||
|
const user2 = {};
|
||||||
|
expect(getDesktopNotificationSound(channelMember2, user2)).toBe('Bing');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
&__reset-btn {
|
&__reset-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
padding: 5px 8px;
|
padding: 5px 8px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@ -58,8 +59,10 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
line-height: 9.5px;
|
|
||||||
place-items: center;
|
i {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:active {
|
&:active {
|
||||||
|
@ -2,54 +2,57 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {screen, fireEvent, waitFor} from '@testing-library/react';
|
import {screen, fireEvent, waitFor} from '@testing-library/react';
|
||||||
import type {ComponentProps} from 'react';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import type {ChannelMembership} from '@mattermost/types/channels';
|
import type {ChannelMembership} from '@mattermost/types/channels';
|
||||||
import type {UserNotifyProps} from '@mattermost/types/users';
|
import type {UserNotifyProps} from '@mattermost/types/users';
|
||||||
|
|
||||||
import ChannelNotificationsModal from 'components/channel_notifications_modal/channel_notifications_modal';
|
import ChannelNotificationsModal, {createChannelNotifyPropsFromSelectedSettings, getInitialValuesOfChannelNotifyProps, areDesktopAndMobileSettingsDifferent} from 'components/channel_notifications_modal/channel_notifications_modal';
|
||||||
|
import type {Props} from 'components/channel_notifications_modal/channel_notifications_modal';
|
||||||
|
|
||||||
import {renderWithContext} from 'tests/react_testing_utils';
|
import {renderWithContext} from 'tests/react_testing_utils';
|
||||||
import {IgnoreChannelMentions, NotificationLevels} from 'utils/constants';
|
import {DesktopSound, IgnoreChannelMentions, NotificationLevels} from 'utils/constants';
|
||||||
|
import {DesktopNotificationSounds, convertDesktopSoundNotifyPropFromUserToDesktop} from 'utils/notification_sounds';
|
||||||
import {TestHelper} from 'utils/test_helper';
|
import {TestHelper} from 'utils/test_helper';
|
||||||
|
|
||||||
describe('components/channel_notifications_modal/ChannelNotificationsModal', () => {
|
describe('ChannelNotificationsModal', () => {
|
||||||
const baseProps: ComponentProps<typeof ChannelNotificationsModal> = {
|
const baseProps: Props = {
|
||||||
onExited: jest.fn(),
|
onExited: jest.fn(),
|
||||||
channel: TestHelper.getChannelMock({
|
channel: TestHelper.getChannelMock({
|
||||||
id: 'channel_id',
|
id: 'channel_id',
|
||||||
display_name: 'channel_display_name',
|
display_name: 'channel_display_name',
|
||||||
}),
|
}),
|
||||||
channelMember: {
|
|
||||||
notify_props: {
|
|
||||||
desktop: NotificationLevels.ALL,
|
|
||||||
desktop_sound: 'on',
|
|
||||||
desktop_notification_sound: 'Bing',
|
|
||||||
mark_unread: NotificationLevels.ALL,
|
|
||||||
push: NotificationLevels.DEFAULT,
|
|
||||||
ignore_channel_mentions: IgnoreChannelMentions.DEFAULT,
|
|
||||||
desktop_threads: NotificationLevels.ALL,
|
|
||||||
push_threads: NotificationLevels.DEFAULT,
|
|
||||||
},
|
|
||||||
} as unknown as ChannelMembership,
|
|
||||||
currentUser: TestHelper.getUserMock({
|
currentUser: TestHelper.getUserMock({
|
||||||
id: 'current_user_id',
|
id: 'current_user_id',
|
||||||
notify_props: {
|
notify_props: {
|
||||||
desktop: NotificationLevels.ALL,
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_threads: NotificationLevels.MENTION,
|
||||||
desktop_sound: 'true',
|
desktop_sound: 'true',
|
||||||
desktop_notification_sound: 'Bing',
|
desktop_notification_sound: 'Bing',
|
||||||
desktop_threads: NotificationLevels.ALL,
|
push: NotificationLevels.MENTION,
|
||||||
|
push_threads: NotificationLevels.MENTION,
|
||||||
} as UserNotifyProps,
|
} as UserNotifyProps,
|
||||||
}),
|
}),
|
||||||
|
channelMember: {
|
||||||
|
notify_props: {
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
desktop_sound: 'on',
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
mark_unread: NotificationLevels.ALL,
|
||||||
|
ignore_channel_mentions: IgnoreChannelMentions.DEFAULT,
|
||||||
|
},
|
||||||
|
} as unknown as ChannelMembership,
|
||||||
sendPushNotifications: true,
|
sendPushNotifications: true,
|
||||||
actions: {
|
actions: {
|
||||||
updateChannelNotifyProps: jest.fn().mockImplementation(() => Promise.resolve({data: true})),
|
updateChannelNotifyProps: jest.fn().mockImplementation(() => Promise.resolve({data: true})),
|
||||||
},
|
},
|
||||||
collapsedReplyThreads: false,
|
collapsedReplyThreads: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should not show other settings if channel is mute', async () => {
|
test('should not show other settings if channel is mute', async () => {
|
||||||
const wrapper = renderWithContext(
|
const wrapper = renderWithContext(
|
||||||
<ChannelNotificationsModal {...baseProps}/>,
|
<ChannelNotificationsModal {...baseProps}/>,
|
||||||
);
|
);
|
||||||
@ -64,7 +67,7 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
expect(screen.queryByText('Desktop Notifications')).toBeNull();
|
expect(screen.queryByText('Desktop Notifications')).toBeNull();
|
||||||
|
|
||||||
expect(screen.queryByText('Mobile Notifications')).toBeNull();
|
expect(screen.queryByText('Mobile Notifications')).toBeNull();
|
||||||
expect(screen.queryByText('Follow all threads in this channel')).toBeNull();
|
expect(screen.queryByText('Follow all threads in this channel')).not.toBeNull();
|
||||||
|
|
||||||
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
||||||
|
|
||||||
@ -73,19 +76,22 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: baseProps.channelMember?.notify_props.desktop,
|
desktop: 'default',
|
||||||
ignore_channel_mentions: 'off',
|
desktop_threads: 'all',
|
||||||
mark_unread: 'mention',
|
desktop_sound: 'default',
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
push: 'all',
|
push: 'all',
|
||||||
desktop_sound: 'on',
|
push_threads: 'all',
|
||||||
desktop_notification_sound: 'Bing',
|
mark_unread: 'mention',
|
||||||
|
ignore_channel_mentions: 'off',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should Ignore mentions for @channel, @here and @all', async () => {
|
test('should save correctly for \'Ignore mentions for @channel, @here and @all\'', async () => {
|
||||||
const wrapper = renderWithContext(
|
const wrapper = renderWithContext(
|
||||||
<ChannelNotificationsModal {...baseProps}/>,
|
<ChannelNotificationsModal {...baseProps}/>,
|
||||||
);
|
);
|
||||||
@ -99,13 +105,15 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: 'all',
|
desktop: 'default',
|
||||||
ignore_channel_mentions: 'on',
|
desktop_threads: 'all',
|
||||||
mark_unread:
|
desktop_sound: 'default',
|
||||||
baseProps.channelMember?.notify_props.mark_unread,
|
desktop_notification_sound: 'default',
|
||||||
push: 'all',
|
push: 'all',
|
||||||
desktop_sound: 'on',
|
push_threads: 'all',
|
||||||
desktop_notification_sound: 'Bing',
|
mark_unread: 'all',
|
||||||
|
ignore_channel_mentions: 'on',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -144,11 +152,14 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: 'none',
|
desktop: 'none',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
|
desktop_threads: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
desktop_sound: 'default',
|
||||||
ignore_channel_mentions: 'off',
|
ignore_channel_mentions: 'off',
|
||||||
mark_unread: 'all',
|
mark_unread: 'all',
|
||||||
push: 'all',
|
push: 'none',
|
||||||
desktop_sound: 'on',
|
|
||||||
desktop_notification_sound: 'Bing',
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -158,7 +169,7 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
test('should disable message notification sound if option is unchecked', async () => {
|
test('should disable message notification sound if option is unchecked', async () => {
|
||||||
renderWithContext(<ChannelNotificationsModal {...baseProps}/>);
|
renderWithContext(<ChannelNotificationsModal {...baseProps}/>);
|
||||||
|
|
||||||
// Since the default value is on, we will uncheck the checkbox
|
// Since the default value is checked, we will uncheck the checkbox
|
||||||
fireEvent.click(screen.getByTestId('desktopNotificationSoundsCheckbox'));
|
fireEvent.click(screen.getByTestId('desktopNotificationSoundsCheckbox'));
|
||||||
expect(screen.getByTestId('desktopNotificationSoundsCheckbox')).not.toBeChecked();
|
expect(screen.getByTestId('desktopNotificationSoundsCheckbox')).not.toBeChecked();
|
||||||
|
|
||||||
@ -168,12 +179,15 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: 'all',
|
desktop: 'default',
|
||||||
ignore_channel_mentions: 'off',
|
desktop_threads: 'all',
|
||||||
mark_unread: 'all',
|
|
||||||
push: 'all',
|
|
||||||
desktop_sound: 'off',
|
desktop_sound: 'off',
|
||||||
desktop_notification_sound: 'Bing',
|
desktop_notification_sound: 'default',
|
||||||
|
push: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
mark_unread: 'all',
|
||||||
|
ignore_channel_mentions: 'off',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -203,7 +217,6 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
const sameAsDesktop: HTMLInputElement = screen.getByTestId(
|
const sameAsDesktop: HTMLInputElement = screen.getByTestId(
|
||||||
'sameMobileSettingsDesktop',
|
'sameMobileSettingsDesktop',
|
||||||
);
|
);
|
||||||
fireEvent.click(sameAsDesktop);
|
|
||||||
expect(sameAsDesktop.checked).toEqual(true);
|
expect(sameAsDesktop.checked).toEqual(true);
|
||||||
|
|
||||||
expect(screen.queryByText('All new messages')).toBeNull();
|
expect(screen.queryByText('All new messages')).toBeNull();
|
||||||
@ -214,12 +227,15 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: 'all',
|
desktop: 'default',
|
||||||
ignore_channel_mentions: 'off',
|
desktop_threads: 'all',
|
||||||
mark_unread: 'all',
|
desktop_sound: 'default',
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
push: 'all',
|
push: 'all',
|
||||||
desktop_sound: 'on',
|
push_threads: 'all',
|
||||||
desktop_notification_sound: 'Bing',
|
mark_unread: 'all',
|
||||||
|
ignore_channel_mentions: 'off',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -227,27 +243,27 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should check the options in the mobile notifications', async () => {
|
test('should check the options in the mobile notifications', async () => {
|
||||||
|
const props = {
|
||||||
|
...baseProps,
|
||||||
|
channelMember: {
|
||||||
|
notify_props: {
|
||||||
|
...baseProps.channelMember?.notify_props,
|
||||||
|
push: NotificationLevels.MENTION,
|
||||||
|
},
|
||||||
|
} as unknown as ChannelMembership,
|
||||||
|
};
|
||||||
const wrapper = renderWithContext(
|
const wrapper = renderWithContext(
|
||||||
<ChannelNotificationsModal {...baseProps}/>,
|
<ChannelNotificationsModal {...props}/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const AlllabelRadio: HTMLInputElement = screen.getByTestId(
|
fireEvent.click(screen.getByTestId('MobileNotification-all'));
|
||||||
'MobileNotification-all',
|
expect(screen.getByTestId('MobileNotification-all')).toBeChecked();
|
||||||
);
|
|
||||||
fireEvent.click(AlllabelRadio);
|
|
||||||
expect(AlllabelRadio.checked).toEqual(true);
|
|
||||||
|
|
||||||
const MentionslabelRadio: HTMLInputElement = screen.getByTestId(
|
fireEvent.click(screen.getByTestId('MobileNotification-mention'));
|
||||||
'MobileNotification-mention',
|
expect(screen.getByTestId('MobileNotification-mention')).toBeChecked();
|
||||||
);
|
|
||||||
fireEvent.click(MentionslabelRadio);
|
|
||||||
expect(MentionslabelRadio.checked).toEqual(true);
|
|
||||||
|
|
||||||
const NothinglabelRadio: HTMLInputElement = screen.getByTestId(
|
fireEvent.click(screen.getByTestId('MobileNotification-none'));
|
||||||
'MobileNotification-none',
|
expect(screen.getByTestId('MobileNotification-none')).toBeChecked();
|
||||||
);
|
|
||||||
fireEvent.click(NothinglabelRadio);
|
|
||||||
expect(NothinglabelRadio.checked).toEqual(true);
|
|
||||||
|
|
||||||
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
@ -255,28 +271,31 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: 'all',
|
desktop: 'default',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
|
desktop_threads: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
desktop_sound: 'default',
|
||||||
ignore_channel_mentions: 'off',
|
ignore_channel_mentions: 'off',
|
||||||
mark_unread: 'all',
|
mark_unread: 'all',
|
||||||
push: 'none',
|
push: 'none',
|
||||||
desktop_sound: 'on',
|
|
||||||
desktop_notification_sound: 'Bing',
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show auto follow, desktop threads and mobile threads settings if collapsed reply threads is enabled', async () => {
|
test('should show not auto follow, desktop threads and mobile threads settings if collapsed reply threads is enabled', async () => {
|
||||||
const props = {
|
const props = {
|
||||||
...baseProps,
|
...baseProps,
|
||||||
collapsedReplyThreads: true,
|
collapsedReplyThreads: false,
|
||||||
};
|
};
|
||||||
const wrapper = renderWithContext(
|
const wrapper = renderWithContext(
|
||||||
<ChannelNotificationsModal {...props}/>,
|
<ChannelNotificationsModal {...props}/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.queryByText('Follow all threads in this channel')).toBeVisible();
|
expect(screen.queryByText('Follow all threads in this channel')).toBeNull();
|
||||||
|
|
||||||
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
fireEvent.click(screen.getByRole('button', {name: /Save/i}));
|
||||||
|
|
||||||
@ -285,18 +304,660 @@ describe('components/channel_notifications_modal/ChannelNotificationsModal', ()
|
|||||||
'current_user_id',
|
'current_user_id',
|
||||||
'channel_id',
|
'channel_id',
|
||||||
{
|
{
|
||||||
desktop: baseProps.channelMember?.notify_props.desktop,
|
channel_auto_follow_threads: 'off',
|
||||||
|
desktop: 'default',
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
desktop_sound: 'default',
|
||||||
|
desktop_threads: 'all',
|
||||||
ignore_channel_mentions: 'off',
|
ignore_channel_mentions: 'off',
|
||||||
mark_unread: 'all',
|
mark_unread: 'all',
|
||||||
channel_auto_follow_threads: 'off',
|
|
||||||
push: 'all',
|
push: 'all',
|
||||||
push_threads: 'default',
|
push_threads: 'all',
|
||||||
desktop_threads: 'all',
|
|
||||||
desktop_sound: 'on',
|
|
||||||
desktop_notification_sound: 'Bing',
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('createChannelNotifyPropsFromSelectedSettings', () => {
|
||||||
|
test('should return passed in mark_unread, ignore_channel_mentions, channel_auto_follow_threads', () => {
|
||||||
|
const userNotifyProps = TestHelper.getUserMock().notify_props;
|
||||||
|
const savedChannelNotifyProps = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
mark_unread: 'all',
|
||||||
|
ignore_channel_mentions: 'off',
|
||||||
|
channel_auto_follow_threads: 'off',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
|
||||||
|
const channelNotifyProps = createChannelNotifyPropsFromSelectedSettings(userNotifyProps, savedChannelNotifyProps, true);
|
||||||
|
expect(channelNotifyProps.mark_unread).toEqual('all');
|
||||||
|
expect(channelNotifyProps.ignore_channel_mentions).toEqual('off');
|
||||||
|
expect(channelNotifyProps.channel_auto_follow_threads).toEqual('off');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return default if channel\'s desktop is same as user\'s desktop value', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.desktop).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'mention',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop).toEqual('default');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return desktop value if channel\'s desktop is different from user\'s desktop value', () => {
|
||||||
|
const userNotifyProps = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
|
||||||
|
const channelNotifyProps = createChannelNotifyPropsFromSelectedSettings(userNotifyProps, savedChannelNotifyProps, true);
|
||||||
|
expect(channelNotifyProps.desktop).toEqual('all');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct desktop_threads when user\'s desktop_threads is defined', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'mention',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.desktop_threads).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'mention',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop_threads).toEqual('mention');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct desktop_threads when user\'s desktop_threads is not defined', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'mention',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.desktop_threads).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'default',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop_threads).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'none',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps3 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps3, savedChannelNotifyProps3, true);
|
||||||
|
expect(channelNotifyProps3.desktop_threads).toEqual('none');
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: '' as any,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'none',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps4 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps4, savedChannelNotifyProps4, true);
|
||||||
|
expect(channelNotifyProps4.desktop_threads).toEqual('none');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct desktop_sound value', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'true',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'on',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.desktop_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
} as UserNotifyProps;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'off',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps3 = {
|
||||||
|
desktop_sound: '' as any,
|
||||||
|
} as UserNotifyProps;
|
||||||
|
const savedChannelNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'on',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps3 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps3, savedChannelNotifyProps3, true);
|
||||||
|
expect(channelNotifyProps3.desktop_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps4 = {
|
||||||
|
desktop_sound: '' as any,
|
||||||
|
} as UserNotifyProps;
|
||||||
|
const savedChannelNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'off',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps4 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps4, savedChannelNotifyProps4, true);
|
||||||
|
expect(channelNotifyProps4.desktop_sound).toEqual('off');
|
||||||
|
|
||||||
|
const userNotifyProps5 = {} as UserNotifyProps;
|
||||||
|
const savedChannelNotifyProps5 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'off',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps5 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps5, savedChannelNotifyProps5, true);
|
||||||
|
expect(channelNotifyProps5.desktop_sound).toEqual('off');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct desktop_notification_sound when user\'s desktop_notification_sound is defined', () => {
|
||||||
|
const userNotifyProps = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps = createChannelNotifyPropsFromSelectedSettings(userNotifyProps, savedChannelNotifyProps, true);
|
||||||
|
expect(channelNotifyProps.desktop_notification_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Crackle',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop_notification_sound).toEqual('Bing');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct desktop_notification_sound when user\'s desktop_notification_sound is not defined', () => {
|
||||||
|
const userNotifyProps = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Bing',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps = createChannelNotifyPropsFromSelectedSettings(userNotifyProps, savedChannelNotifyProps, true);
|
||||||
|
expect(channelNotifyProps.desktop_notification_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'default',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.desktop_notification_sound).toEqual('default');
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: 'Crackle',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps3 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps3, savedChannelNotifyProps3, true);
|
||||||
|
expect(channelNotifyProps3.desktop_notification_sound).toEqual('Crackle');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct push value', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.push).toEqual('all');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.push).toEqual('default');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct push value when desktop and mobile settings are the same', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
push: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
push: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, false);
|
||||||
|
expect(channelNotifyProps1.push).toEqual('all');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
push: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'mention',
|
||||||
|
push: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, false);
|
||||||
|
expect(channelNotifyProps2.push).toEqual('mention');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct push_threads value', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'mention',
|
||||||
|
push_threads: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps1 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps1, savedChannelNotifyProps1, true);
|
||||||
|
expect(channelNotifyProps1.push).toEqual('all');
|
||||||
|
expect(channelNotifyProps1.push_threads).toEqual('all');
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'mention',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps2 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps2, savedChannelNotifyProps2, true);
|
||||||
|
expect(channelNotifyProps2.push).toEqual('all');
|
||||||
|
expect(channelNotifyProps2.push_threads).toEqual('all');
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: 'all',
|
||||||
|
push_threads: 'all',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps3 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps3, savedChannelNotifyProps3, true);
|
||||||
|
expect(channelNotifyProps3.push).toEqual('all');
|
||||||
|
expect(channelNotifyProps3.push_threads).toEqual('all');
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'mention',
|
||||||
|
push_threads: 'none',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps4 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps4, savedChannelNotifyProps4, false);
|
||||||
|
expect(channelNotifyProps4.push_threads).toEqual('mention');
|
||||||
|
|
||||||
|
const userNotifyProps5 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'none',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const savedChannelNotifyProps5 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: 'all',
|
||||||
|
push_threads: 'none',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const channelNotifyProps5 = createChannelNotifyPropsFromSelectedSettings(userNotifyProps5, savedChannelNotifyProps5, false);
|
||||||
|
expect(channelNotifyProps5.push_threads).toEqual('all');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getInitialValuesOfChannelNotifyProps', () => {
|
||||||
|
test('should return correct value for desktop', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'all',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: 'default',
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktop = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps1.desktop, userNotifyProps1.desktop);
|
||||||
|
expect(desktop).toEqual(NotificationLevels.ALL);
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: NotificationLevels.MENTION,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktop2 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps2.desktop, userNotifyProps2.desktop);
|
||||||
|
expect(desktop2).toEqual(NotificationLevels.MENTION);
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktop3 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps3.desktop, userNotifyProps3.desktop);
|
||||||
|
expect(desktop3).toEqual(NotificationLevels.ALL);
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktop4 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps4.desktop, userNotifyProps4.desktop);
|
||||||
|
expect(desktop4).toEqual(NotificationLevels.ALL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct value for desktop_threads', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: NotificationLevels.DEFAULT,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopThreads = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps1.desktop_threads, userNotifyProps1.desktop_threads);
|
||||||
|
expect(desktopThreads).toEqual(NotificationLevels.ALL);
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: NotificationLevels.MENTION,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopThreads2 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps2.desktop_threads, userNotifyProps2.desktop_threads);
|
||||||
|
expect(desktopThreads2).toEqual(NotificationLevels.MENTION);
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopThreads3 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps3.desktop_threads, userNotifyProps3.desktop_threads);
|
||||||
|
expect(desktopThreads3).toEqual(NotificationLevels.ALL);
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopThreads4 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps4.desktop_threads, userNotifyProps4.desktop_threads);
|
||||||
|
expect(desktopThreads4).toEqual(NotificationLevels.ALL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct value for desktop_sound', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: DesktopSound.DEFAULT,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopSound = getInitialValuesOfChannelNotifyProps(DesktopSound.ON, channelMemberNotifyProps1?.desktop_sound, convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps1?.desktop_sound));
|
||||||
|
expect(desktopSound).toEqual(DesktopSound.OFF);
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: DesktopSound.OFF,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopSound2 = getInitialValuesOfChannelNotifyProps(DesktopSound.ON, channelMemberNotifyProps2?.desktop_sound, convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps2?.desktop_sound));
|
||||||
|
expect(desktopSound2).toEqual(DesktopSound.OFF);
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_sound: 'false',
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopSound3 = getInitialValuesOfChannelNotifyProps(DesktopSound.ON, channelMemberNotifyProps3?.desktop_sound, convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps3?.desktop_sound));
|
||||||
|
expect(desktopSound3).toEqual(DesktopSound.OFF);
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopSound4 = getInitialValuesOfChannelNotifyProps(DesktopSound.ON, channelMemberNotifyProps4?.desktop_sound, convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps4?.desktop_sound));
|
||||||
|
expect(desktopSound4).toEqual(DesktopSound.ON);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct value for desktop_notification_sound', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: DesktopNotificationSounds.BING,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: DesktopNotificationSounds.DEFAULT,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopNotificationSound = getInitialValuesOfChannelNotifyProps(DesktopNotificationSounds.BING, channelMemberNotifyProps1?.desktop_notification_sound, userNotifyProps1?.desktop_notification_sound);
|
||||||
|
expect(desktopNotificationSound).toEqual(DesktopNotificationSounds.BING);
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: DesktopNotificationSounds.CRACKLE,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: DesktopNotificationSounds.BING,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopNotificationSound2 = getInitialValuesOfChannelNotifyProps(DesktopNotificationSounds.BING, channelMemberNotifyProps2?.desktop_notification_sound, userNotifyProps2?.desktop_notification_sound);
|
||||||
|
expect(desktopNotificationSound2).toEqual(DesktopNotificationSounds.BING);
|
||||||
|
|
||||||
|
const userNotifyProps3 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
desktop_notification_sound: DesktopNotificationSounds.CRACKLE,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps3 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopNotificationSound3 = getInitialValuesOfChannelNotifyProps(DesktopNotificationSounds.BING, channelMemberNotifyProps3?.desktop_notification_sound, userNotifyProps3?.desktop_notification_sound);
|
||||||
|
expect(desktopNotificationSound3).toEqual(DesktopNotificationSounds.CRACKLE);
|
||||||
|
|
||||||
|
const userNotifyProps4 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps4 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const desktopNotificationSound4 = getInitialValuesOfChannelNotifyProps(DesktopNotificationSounds.BING, channelMemberNotifyProps4?.desktop_notification_sound, userNotifyProps4?.desktop_notification_sound);
|
||||||
|
expect(desktopNotificationSound4).toEqual(DesktopNotificationSounds.BING);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct value for push', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push: NotificationLevels.DEFAULT,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const push = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps1.push, userNotifyProps1.push);
|
||||||
|
expect(push).toEqual(NotificationLevels.ALL);
|
||||||
|
|
||||||
|
const userNotifyProps2 = TestHelper.getUserMock({
|
||||||
|
notify_props: {} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps2 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {},
|
||||||
|
}).notify_props;
|
||||||
|
const push2 = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps2.push, userNotifyProps2.push);
|
||||||
|
expect(push2).toEqual(NotificationLevels.ALL);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return correct value for push_threads', () => {
|
||||||
|
const userNotifyProps1 = TestHelper.getUserMock({
|
||||||
|
notify_props: {
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
} as UserNotifyProps,
|
||||||
|
}).notify_props;
|
||||||
|
const channelMemberNotifyProps1 = TestHelper.getChannelMembershipMock({
|
||||||
|
notify_props: {
|
||||||
|
push_threads: NotificationLevels.DEFAULT,
|
||||||
|
},
|
||||||
|
}).notify_props;
|
||||||
|
const pushThreads = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, channelMemberNotifyProps1.push_threads, userNotifyProps1.push_threads);
|
||||||
|
expect(pushThreads).toEqual(NotificationLevels.ALL);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('areDesktopAndMobileSettingsDifferent', () => {
|
||||||
|
test('should return correct value for collapsed threads', () => {
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.ALL, NotificationLevels.ALL, NotificationLevels.DEFAULT, NotificationLevels.DEFAULT)).toEqual(true);
|
||||||
|
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.ALL, NotificationLevels.ALL, NotificationLevels.ALL, NotificationLevels.ALL)).toEqual(false);
|
||||||
|
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.ALL, NotificationLevels.ALL)).toEqual(true);
|
||||||
|
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.ALL, NotificationLevels.ALL, NotificationLevels.ALL)).toEqual(true);
|
||||||
|
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.MENTION, NotificationLevels.ALL, NotificationLevels.MENTION, NotificationLevels.ALL)).toEqual(false);
|
||||||
|
|
||||||
|
expect(areDesktopAndMobileSettingsDifferent(true, NotificationLevels.DEFAULT, NotificationLevels.DEFAULT)).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -6,8 +6,8 @@ import {Modal} from 'react-bootstrap';
|
|||||||
import {FormattedMessage, useIntl} from 'react-intl';
|
import {FormattedMessage, useIntl} from 'react-intl';
|
||||||
import type {ValueType} from 'react-select';
|
import type {ValueType} from 'react-select';
|
||||||
|
|
||||||
import {BellOffOutlineIcon, RefreshIcon} from '@mattermost/compass-icons/components';
|
import {BellOffOutlineIcon} from '@mattermost/compass-icons/components';
|
||||||
import type {Channel, ChannelNotifyProps} from '@mattermost/types/channels';
|
import type {Channel, ChannelMembership, ChannelNotifyProps} from '@mattermost/types/channels';
|
||||||
import type {UserNotifyProps, UserProfile} from '@mattermost/types/users';
|
import type {UserNotifyProps, UserProfile} from '@mattermost/types/users';
|
||||||
|
|
||||||
import AlertBanner from 'components/alert_banner';
|
import AlertBanner from 'components/alert_banner';
|
||||||
@ -18,17 +18,17 @@ import ModalSection from 'components/widgets/modals/components/modal_section';
|
|||||||
import RadioSettingItem from 'components/widgets/modals/components/radio_setting_item';
|
import RadioSettingItem from 'components/widgets/modals/components/radio_setting_item';
|
||||||
import type {Option} from 'components/widgets/modals/components/react_select_item';
|
import type {Option} from 'components/widgets/modals/components/react_select_item';
|
||||||
|
|
||||||
import {IgnoreChannelMentions, NotificationLevels, DesktopSound} from 'utils/constants';
|
import {NotificationLevels, DesktopSound, IgnoreChannelMentions} from 'utils/constants';
|
||||||
import {getValueOfNotificationSoundsSelect, notificationSoundKeys, stopTryNotificationRing, tryNotificationSound} from 'utils/notification_sounds';
|
import {convertDesktopSoundNotifyPropFromUserToDesktop, DesktopNotificationSounds, getValueOfNotificationSoundsSelect, stopTryNotificationRing, tryNotificationSound} from 'utils/notification_sounds';
|
||||||
|
|
||||||
import type {ChannelMemberNotifyProps} from './utils';
|
import ResetToDefaultButton, {SectionName} from './reset_to_default_button';
|
||||||
import utils, {convertDesktopSoundNotifyPropFromUserToDesktop} from './utils';
|
import utils from './utils';
|
||||||
|
|
||||||
import type {PropsFromRedux} from './index';
|
import type {PropsFromRedux} from './index';
|
||||||
|
|
||||||
import './channel_notifications_modal.scss';
|
import './channel_notifications_modal.scss';
|
||||||
|
|
||||||
type Props = PropsFromRedux & {
|
export type Props = PropsFromRedux & {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that is called when the modal has been hidden and should be removed
|
* Function that is called when the modal has been hidden and should be removed
|
||||||
@ -46,74 +46,21 @@ type Props = PropsFromRedux & {
|
|||||||
currentUser: UserProfile;
|
currentUser: UserProfile;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getUseSameDesktopSetting(currentUserNotifyProps: UserNotifyProps, channelMemberNotifyProps?: ChannelMemberNotifyProps) {
|
|
||||||
const isSameAsDesktop = channelMemberNotifyProps ? channelMemberNotifyProps?.desktop === channelMemberNotifyProps?.push : currentUserNotifyProps.push === currentUserNotifyProps.desktop;
|
|
||||||
const isSameAsDesktopThreads = channelMemberNotifyProps ? channelMemberNotifyProps?.desktop_threads === channelMemberNotifyProps?.push_threads : currentUserNotifyProps.push_threads === currentUserNotifyProps.desktop_threads;
|
|
||||||
return isSameAsDesktop && isSameAsDesktopThreads;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateFromNotifyProps(currentUserNotifyProps: UserNotifyProps, channelMemberNotifyProps?: ChannelMemberNotifyProps) {
|
|
||||||
let ignoreChannelMentionsDefault: ChannelNotifyProps['ignore_channel_mentions'] = IgnoreChannelMentions.OFF;
|
|
||||||
|
|
||||||
if (channelMemberNotifyProps?.mark_unread === NotificationLevels.MENTION || (currentUserNotifyProps.channel && currentUserNotifyProps.channel === 'false')) {
|
|
||||||
ignoreChannelMentionsDefault = IgnoreChannelMentions.ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ignoreChannelMentions = channelMemberNotifyProps?.ignore_channel_mentions;
|
|
||||||
if (!ignoreChannelMentions || ignoreChannelMentions === IgnoreChannelMentions.DEFAULT) {
|
|
||||||
ignoreChannelMentions = ignoreChannelMentionsDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
const desktop = channelMemberNotifyProps?.desktop === NotificationLevels.DEFAULT ? currentUserNotifyProps.desktop : (channelMemberNotifyProps?.desktop || currentUserNotifyProps.desktop);
|
|
||||||
const push = channelMemberNotifyProps?.push === NotificationLevels.DEFAULT ? currentUserNotifyProps.desktop : (channelMemberNotifyProps?.push || currentUserNotifyProps.push);
|
|
||||||
|
|
||||||
let desktopSound;
|
|
||||||
if (channelMemberNotifyProps && channelMemberNotifyProps.desktop_sound) {
|
|
||||||
desktopSound = channelMemberNotifyProps.desktop_sound;
|
|
||||||
} else {
|
|
||||||
desktopSound = convertDesktopSoundNotifyPropFromUserToDesktop(currentUserNotifyProps.desktop_sound);
|
|
||||||
}
|
|
||||||
|
|
||||||
let desktopNotificationSound;
|
|
||||||
if (channelMemberNotifyProps && channelMemberNotifyProps.desktop_notification_sound) {
|
|
||||||
desktopNotificationSound = channelMemberNotifyProps.desktop_notification_sound;
|
|
||||||
} else if (currentUserNotifyProps && currentUserNotifyProps.desktop_notification_sound) {
|
|
||||||
desktopNotificationSound = currentUserNotifyProps.desktop_notification_sound;
|
|
||||||
} else {
|
|
||||||
desktopNotificationSound = notificationSoundKeys[0] as ChannelNotifyProps['desktop_notification_sound'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
desktop,
|
|
||||||
desktop_threads: channelMemberNotifyProps?.desktop_threads || NotificationLevels.ALL,
|
|
||||||
desktop_sound: desktopSound,
|
|
||||||
desktop_notification_sound: desktopNotificationSound,
|
|
||||||
mark_unread: channelMemberNotifyProps?.mark_unread || NotificationLevels.ALL,
|
|
||||||
push,
|
|
||||||
push_threads: channelMemberNotifyProps?.push_threads || NotificationLevels.ALL,
|
|
||||||
ignore_channel_mentions: ignoreChannelMentions,
|
|
||||||
channel_auto_follow_threads: channelMemberNotifyProps?.channel_auto_follow_threads || 'off',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type SettingsType = {
|
|
||||||
desktop: ChannelNotifyProps['desktop'];
|
|
||||||
desktop_threads: ChannelNotifyProps['desktop_threads'];
|
|
||||||
desktop_sound: ChannelNotifyProps['desktop_sound'];
|
|
||||||
desktop_notification_sound: ChannelNotifyProps['desktop_notification_sound'];
|
|
||||||
mark_unread: ChannelNotifyProps['mark_unread'];
|
|
||||||
push: ChannelNotifyProps['push'];
|
|
||||||
push_threads: ChannelNotifyProps['push_threads'];
|
|
||||||
ignore_channel_mentions: ChannelNotifyProps['ignore_channel_mentions'];
|
|
||||||
channel_auto_follow_threads: ChannelNotifyProps['channel_auto_follow_threads'];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ChannelNotificationsModal(props: Props) {
|
export default function ChannelNotificationsModal(props: Props) {
|
||||||
const {formatMessage} = useIntl();
|
const {formatMessage} = useIntl();
|
||||||
|
|
||||||
const [show, setShow] = useState(true);
|
const [show, setShow] = useState(true);
|
||||||
const [serverError, setServerError] = useState('');
|
const [serverError, setServerError] = useState('');
|
||||||
const [mobileSettingsSameAsDesktop, setMobileSettingsSameAsDesktop] = useState<boolean>(getUseSameDesktopSetting(props.currentUser.notify_props, props.channelMember?.notify_props));
|
|
||||||
const [settings, setSettings] = useState<SettingsType>(getStateFromNotifyProps(props.currentUser.notify_props, props.channelMember?.notify_props));
|
const [settings, setSettings] = useState(getStateFromNotifyProps(props.currentUser.notify_props, props.channelMember?.notify_props));
|
||||||
|
|
||||||
|
const [desktopAndMobileSettingsDifferent, setDesktopAndMobileSettingDifferent] = useState<boolean>(areDesktopAndMobileSettingsDifferent(
|
||||||
|
props.collapsedReplyThreads,
|
||||||
|
getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props?.channelMember?.notify_props?.desktop, props.currentUser.notify_props.desktop),
|
||||||
|
getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props?.channelMember?.notify_props?.desktop_threads, props.currentUser.notify_props.desktop_threads),
|
||||||
|
getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props?.channelMember?.notify_props?.push, props.currentUser.notify_props.push),
|
||||||
|
getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props?.channelMember?.notify_props?.push_threads, props.currentUser.notify_props.push_threads),
|
||||||
|
));
|
||||||
|
|
||||||
function handleHide() {
|
function handleHide() {
|
||||||
setShow(false);
|
setShow(false);
|
||||||
@ -123,10 +70,49 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
setSettings((prevSettings) => ({...prevSettings, ...values}));
|
setSettings((prevSettings) => ({...prevSettings, ...values}));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleMobileSettingsChange = useCallback(() => {
|
function handleUseSameMobileSettingsAsDesktopCheckboxChange(value: boolean) {
|
||||||
setMobileSettingsSameAsDesktop((prevSettings) => !prevSettings);
|
const newValueOfSettings = {...settings};
|
||||||
setSettings((prevSettings) => ({...prevSettings, push: prevSettings.desktop, push_threads: prevSettings.desktop_threads}));
|
const newValueOfDesktopAndMobileSettingsDifferent = !value;
|
||||||
}, []);
|
|
||||||
|
if (newValueOfDesktopAndMobileSettingsDifferent === false) {
|
||||||
|
newValueOfSettings.push = settings.desktop;
|
||||||
|
newValueOfSettings.push_threads = settings.desktop_threads;
|
||||||
|
} else {
|
||||||
|
newValueOfSettings.push = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props.channelMember?.notify_props?.push, props.currentUser?.notify_props?.push);
|
||||||
|
newValueOfSettings.push_threads = getInitialValuesOfChannelNotifyProps(NotificationLevels.ALL, props.channelMember?.notify_props?.push_threads, props.currentUser?.notify_props?.push_threads);
|
||||||
|
}
|
||||||
|
setSettings(newValueOfSettings);
|
||||||
|
setDesktopAndMobileSettingDifferent(newValueOfDesktopAndMobileSettingsDifferent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResetToDefaultClicked(channelNotifyPropsDefaultedToUserNotifyProps: ChannelMembership['notify_props'], sectionName: SectionName) {
|
||||||
|
if (sectionName === SectionName.Mobile) {
|
||||||
|
const desktopAndMobileSettingsDifferent = areDesktopAndMobileSettingsDifferent(
|
||||||
|
props.collapsedReplyThreads,
|
||||||
|
settings.desktop,
|
||||||
|
settings.desktop_threads,
|
||||||
|
channelNotifyPropsDefaultedToUserNotifyProps.push,
|
||||||
|
channelNotifyPropsDefaultedToUserNotifyProps.push_threads,
|
||||||
|
);
|
||||||
|
|
||||||
|
setDesktopAndMobileSettingDifferent(desktopAndMobileSettingsDifferent);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSettings({...settings, ...channelNotifyPropsDefaultedToUserNotifyProps});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSave() {
|
||||||
|
const channelNotifyProps = createChannelNotifyPropsFromSelectedSettings(props.currentUser.notify_props, settings, desktopAndMobileSettingsDifferent);
|
||||||
|
|
||||||
|
props.actions.updateChannelNotifyProps(props.currentUser.id, props.channel.id, channelNotifyProps).then((value) => {
|
||||||
|
const {error} = value;
|
||||||
|
if (error) {
|
||||||
|
setServerError(error.message);
|
||||||
|
} else {
|
||||||
|
handleHide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const muteOrIgnoreSectionContent = (
|
const muteOrIgnoreSectionContent = (
|
||||||
<>
|
<>
|
||||||
@ -179,7 +165,7 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
id: 'channel_notifications.NotifyMeTitle',
|
id: 'channel_notifications.NotifyMeTitle',
|
||||||
defaultMessage: 'Notify me about…',
|
defaultMessage: 'Notify me about…',
|
||||||
})}
|
})}
|
||||||
inputFieldValue={settings.desktop}
|
inputFieldValue={settings.desktop || ''}
|
||||||
inputFieldData={utils.desktopNotificationInputFieldData(props.currentUser.notify_props.desktop)}
|
inputFieldData={utils.desktopNotificationInputFieldData(props.currentUser.notify_props.desktop)}
|
||||||
handleChange={(e) => handleChange({desktop: e.target.value})}
|
handleChange={(e) => handleChange({desktop: e.target.value})}
|
||||||
/>
|
/>
|
||||||
@ -237,23 +223,25 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
defaultMessage='Use the same notification settings as desktop'
|
defaultMessage='Use the same notification settings as desktop'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
inputFieldValue={mobileSettingsSameAsDesktop}
|
inputFieldValue={!desktopAndMobileSettingsDifferent}
|
||||||
inputFieldData={utils.sameMobileSettingsDesktopInputFieldData}
|
inputFieldData={utils.sameMobileSettingsDesktopInputFieldData}
|
||||||
handleChange={() => handleMobileSettingsChange()}
|
handleChange={handleUseSameMobileSettingsAsDesktopCheckboxChange}
|
||||||
/>
|
/>
|
||||||
{!mobileSettingsSameAsDesktop && (
|
{desktopAndMobileSettingsDifferent && (
|
||||||
<>
|
<>
|
||||||
<RadioSettingItem
|
<RadioSettingItem
|
||||||
|
dataTestId='mobile-notify-me-radio-section'
|
||||||
title={formatMessage({
|
title={formatMessage({
|
||||||
id: 'channel_notifications.NotifyMeTitle',
|
id: 'channel_notifications.NotifyMeTitle',
|
||||||
defaultMessage: 'Notify me about…',
|
defaultMessage: 'Notify me about…',
|
||||||
})}
|
})}
|
||||||
inputFieldValue={settings.push}
|
inputFieldValue={settings.push || ''}
|
||||||
inputFieldData={utils.mobileNotificationInputFieldData(props.currentUser.notify_props.push)}
|
inputFieldData={utils.mobileNotificationInputFieldData(props.currentUser.notify_props.push)}
|
||||||
handleChange={(e) => handleChange({push: e.target.value})}
|
handleChange={(e) => handleChange({push: e.target.value})}
|
||||||
/>
|
/>
|
||||||
{props.collapsedReplyThreads && settings.push === 'mention' &&
|
{props.collapsedReplyThreads && settings.push === 'mention' &&
|
||||||
<CheckboxSettingItem
|
<CheckboxSettingItem
|
||||||
|
dataTestId='mobile-reply-threads-checkbox-section'
|
||||||
title={formatMessage({
|
title={formatMessage({
|
||||||
id: 'channel_notifications.ThreadsReplyTitle',
|
id: 'channel_notifications.ThreadsReplyTitle',
|
||||||
defaultMessage: 'Thread reply notifications',
|
defaultMessage: 'Thread reply notifications',
|
||||||
@ -287,75 +275,6 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
function handleSave() {
|
|
||||||
const userSettings: Partial<SettingsType> = {...settings};
|
|
||||||
if (!props.collapsedReplyThreads) {
|
|
||||||
delete userSettings.push_threads;
|
|
||||||
delete userSettings.desktop_threads;
|
|
||||||
delete userSettings.channel_auto_follow_threads;
|
|
||||||
}
|
|
||||||
props.actions.updateChannelNotifyProps(props.currentUser.id, props.channel.id, userSettings).then((value) => {
|
|
||||||
const {error} = value;
|
|
||||||
if (error) {
|
|
||||||
setServerError(error.message);
|
|
||||||
} else {
|
|
||||||
handleHide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetToDefaultBtn = useCallback((sectionName: string) => {
|
|
||||||
const userNotifyProps = {
|
|
||||||
...props.currentUser.notify_props,
|
|
||||||
desktop_notification_sound: props.currentUser.notify_props?.desktop_notification_sound ?? notificationSoundKeys[0] as ChannelNotifyProps['desktop_notification_sound'],
|
|
||||||
};
|
|
||||||
|
|
||||||
function resetToDefault(sectionName: string) {
|
|
||||||
if (sectionName === 'desktop') {
|
|
||||||
setSettings({
|
|
||||||
...settings,
|
|
||||||
desktop: userNotifyProps.desktop,
|
|
||||||
desktop_threads: userNotifyProps.desktop_threads || settings.desktop_threads,
|
|
||||||
desktop_sound: convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps.desktop_sound),
|
|
||||||
desktop_notification_sound: userNotifyProps?.desktop_notification_sound ?? notificationSoundKeys[0] as ChannelNotifyProps['desktop_notification_sound'],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sectionName === 'push') {
|
|
||||||
setSettings({...settings, push: userNotifyProps.desktop, push_threads: userNotifyProps.push_threads || settings.push_threads});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isDesktopSameAsDefault =
|
|
||||||
userNotifyProps.desktop === settings.desktop &&
|
|
||||||
userNotifyProps.desktop_threads === settings.desktop_threads &&
|
|
||||||
userNotifyProps.desktop_notification_sound === settings.desktop_notification_sound &&
|
|
||||||
convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps.desktop_sound) === settings.desktop_sound;
|
|
||||||
|
|
||||||
const isPushSameAsDefault = (userNotifyProps.push === settings.push && userNotifyProps.push_threads === settings.push_threads);
|
|
||||||
|
|
||||||
if ((sectionName === 'desktop' && isDesktopSameAsDefault) || (sectionName === 'push' && isPushSameAsDefault)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className='channel-notifications-settings-modal__reset-btn'
|
|
||||||
onClick={() => resetToDefault(sectionName)}
|
|
||||||
data-testid={`resetToDefaultButton-${sectionName}`}
|
|
||||||
>
|
|
||||||
<RefreshIcon
|
|
||||||
size={14}
|
|
||||||
color={'currentColor'}
|
|
||||||
/>
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.resetToDefault'
|
|
||||||
defaultMessage='Reset to default'
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}, [props.currentUser.notify_props, settings]);
|
|
||||||
|
|
||||||
const desktopAndMobileNotificationSectionContent = settings.mark_unread === 'all' ? (
|
const desktopAndMobileNotificationSectionContent = settings.mark_unread === 'all' ? (
|
||||||
<>
|
<>
|
||||||
<div className='channel-notifications-settings-modal__divider'/>
|
<div className='channel-notifications-settings-modal__divider'/>
|
||||||
@ -364,7 +283,14 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
id: 'channel_notifications.desktopNotificationsTitle',
|
id: 'channel_notifications.desktopNotificationsTitle',
|
||||||
defaultMessage: 'Desktop Notifications',
|
defaultMessage: 'Desktop Notifications',
|
||||||
})}
|
})}
|
||||||
titleSuffix={resetToDefaultBtn('desktop')}
|
titleSuffix={
|
||||||
|
<ResetToDefaultButton
|
||||||
|
sectionName={SectionName.Desktop}
|
||||||
|
userNotifyProps={props.currentUser.notify_props}
|
||||||
|
userSelectedChannelNotifyProps={settings}
|
||||||
|
onClick={handleResetToDefaultClicked}
|
||||||
|
/>
|
||||||
|
}
|
||||||
description={formatMessage({
|
description={formatMessage({
|
||||||
id: 'channel_notifications.desktopNotificationsDesc',
|
id: 'channel_notifications.desktopNotificationsDesc',
|
||||||
defaultMessage: 'Available on Chrome, Edge, Firefox, and the Mattermost Desktop App.',
|
defaultMessage: 'Available on Chrome, Edge, Firefox, and the Mattermost Desktop App.',
|
||||||
@ -377,7 +303,14 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
id: 'channel_notifications.mobileNotificationsTitle',
|
id: 'channel_notifications.mobileNotificationsTitle',
|
||||||
defaultMessage: 'Mobile Notifications',
|
defaultMessage: 'Mobile Notifications',
|
||||||
})}
|
})}
|
||||||
titleSuffix={resetToDefaultBtn('push')}
|
titleSuffix={
|
||||||
|
<ResetToDefaultButton
|
||||||
|
sectionName={SectionName.Mobile}
|
||||||
|
userNotifyProps={props.currentUser.notify_props}
|
||||||
|
userSelectedChannelNotifyProps={settings}
|
||||||
|
onClick={handleResetToDefaultClicked}
|
||||||
|
/>
|
||||||
|
}
|
||||||
description={formatMessage({
|
description={formatMessage({
|
||||||
id: 'channel_notifications.mobileNotificationsDesc',
|
id: 'channel_notifications.mobileNotificationsDesc',
|
||||||
defaultMessage: 'Notification alerts are pushed to your mobile device when there is activity in Mattermost.',
|
defaultMessage: 'Notification alerts are pushed to your mobile device when there is activity in Mattermost.',
|
||||||
@ -485,3 +418,176 @@ export default function ChannelNotificationsModal(props: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getStateFromNotifyProps(currentUserNotifyProps: UserNotifyProps, channelMemberNotifyProps?: ChannelMembership['notify_props']): Required<Omit<ChannelMembership['notify_props'], 'email'>> {
|
||||||
|
return {
|
||||||
|
mark_unread: channelMemberNotifyProps?.mark_unread ?? NotificationLevels.ALL,
|
||||||
|
ignore_channel_mentions: getInitialValuesOfIgnoreChannelMentions(channelMemberNotifyProps?.mark_unread, channelMemberNotifyProps?.ignore_channel_mentions, currentUserNotifyProps?.channel),
|
||||||
|
desktop: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['desktop']>(NotificationLevels.ALL, channelMemberNotifyProps?.desktop, currentUserNotifyProps?.desktop),
|
||||||
|
desktop_threads: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['desktop_threads']>(NotificationLevels.ALL, channelMemberNotifyProps?.desktop_threads, currentUserNotifyProps?.desktop_threads),
|
||||||
|
desktop_sound: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['desktop_sound']>(DesktopSound.ON, channelMemberNotifyProps?.desktop_sound, convertDesktopSoundNotifyPropFromUserToDesktop(currentUserNotifyProps?.desktop_sound)),
|
||||||
|
desktop_notification_sound: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['desktop_notification_sound']>(DesktopNotificationSounds.BING, channelMemberNotifyProps?.desktop_notification_sound, currentUserNotifyProps?.desktop_notification_sound),
|
||||||
|
push: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['push']>(NotificationLevels.ALL, channelMemberNotifyProps?.push, currentUserNotifyProps?.push),
|
||||||
|
push_threads: getInitialValuesOfChannelNotifyProps<ChannelMembership['notify_props']['push_threads']>(NotificationLevels.ALL, channelMemberNotifyProps?.push_threads, currentUserNotifyProps?.push_threads),
|
||||||
|
channel_auto_follow_threads: channelMemberNotifyProps?.channel_auto_follow_threads ?? 'off',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInitialValuesOfChannelNotifyProps<KeyInNotifyProps>(defaultValue: NonNullable<KeyInNotifyProps>, channelMemberNotifyProp: KeyInNotifyProps | undefined = undefined, userNotifyProp: KeyInNotifyProps | undefined = undefined) {
|
||||||
|
let value = defaultValue;
|
||||||
|
|
||||||
|
// Check if channel_member's notify_prop is defined for the selected notify_prop
|
||||||
|
if (channelMemberNotifyProp) {
|
||||||
|
// If channel_member's notify_prop is default and user's notify_prop is defined, we should use user's notify_prop
|
||||||
|
if (channelMemberNotifyProp === NotificationLevels.DEFAULT && userNotifyProp) {
|
||||||
|
value = userNotifyProp;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use channel_member's notify_prop as is
|
||||||
|
value = channelMemberNotifyProp;
|
||||||
|
}
|
||||||
|
} else if (userNotifyProp) {
|
||||||
|
// If channel_member's notify_prop is not defined and user's notify_prop is defined, we should use user's notify_prop as is
|
||||||
|
value = userNotifyProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInitialValuesOfIgnoreChannelMentions(
|
||||||
|
markUnread: ChannelMembership['notify_props']['mark_unread'],
|
||||||
|
ignoreChannelMentions: ChannelMembership['notify_props']['ignore_channel_mentions'],
|
||||||
|
userNotifyPropForChannel: UserNotifyProps['channel'],
|
||||||
|
): NonNullable<ChannelMembership['notify_props']['ignore_channel_mentions']> {
|
||||||
|
let ignoreChannelMentionsDefault: ChannelNotifyProps['ignore_channel_mentions'] = IgnoreChannelMentions.OFF;
|
||||||
|
if (markUnread === NotificationLevels.MENTION || (userNotifyPropForChannel && userNotifyPropForChannel === 'false')) {
|
||||||
|
ignoreChannelMentionsDefault = IgnoreChannelMentions.ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoreChannelMentions) {
|
||||||
|
if (ignoreChannelMentions === IgnoreChannelMentions.DEFAULT) {
|
||||||
|
return ignoreChannelMentionsDefault;
|
||||||
|
}
|
||||||
|
return ignoreChannelMentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ignoreChannelMentionsDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createChannelNotifyPropsFromSelectedSettings(
|
||||||
|
userNotifyProps: UserNotifyProps,
|
||||||
|
savedChannelNotifyProps: ChannelMembership['notify_props'],
|
||||||
|
desktopAndMobileSettingsDifferent: boolean,
|
||||||
|
) {
|
||||||
|
const channelNotifyProps: ChannelMembership['notify_props'] = {
|
||||||
|
mark_unread: savedChannelNotifyProps.mark_unread,
|
||||||
|
ignore_channel_mentions: savedChannelNotifyProps.ignore_channel_mentions,
|
||||||
|
channel_auto_follow_threads: savedChannelNotifyProps.channel_auto_follow_threads,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (savedChannelNotifyProps.desktop === userNotifyProps.desktop) {
|
||||||
|
channelNotifyProps.desktop = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
channelNotifyProps.desktop = savedChannelNotifyProps.desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if USER's desktop_thread setting are defined
|
||||||
|
if (userNotifyProps?.desktop_threads?.length) {
|
||||||
|
// If USER's desktop_thread setting is same as CHANNEL's new desktop_threads setting, we should set it to default
|
||||||
|
if (userNotifyProps.desktop_threads === savedChannelNotifyProps.desktop_threads) {
|
||||||
|
channelNotifyProps.desktop_threads = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new desktop_threads setting as is
|
||||||
|
channelNotifyProps.desktop_threads = savedChannelNotifyProps.desktop_threads;
|
||||||
|
}
|
||||||
|
} else if (savedChannelNotifyProps.desktop_threads === NotificationLevels.MENTION || savedChannelNotifyProps.desktop_threads === NotificationLevels.DEFAULT) {
|
||||||
|
// If USER's desktop_thread setting is not defined and CHANNEL's new desktop_threads setting is MENTION or DEFAULT, then save it as default
|
||||||
|
channelNotifyProps.desktop_threads = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new desktop_threads setting as is
|
||||||
|
channelNotifyProps.desktop_threads = savedChannelNotifyProps.desktop_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps?.desktop_sound) === savedChannelNotifyProps.desktop_sound) {
|
||||||
|
channelNotifyProps.desktop_sound = DesktopSound.DEFAULT;
|
||||||
|
} else {
|
||||||
|
channelNotifyProps.desktop_sound = savedChannelNotifyProps.desktop_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if USER's desktop_notification_sound setting is defined
|
||||||
|
if (userNotifyProps?.desktop_notification_sound?.length) {
|
||||||
|
// If USER's desktop_notification_sound setting is same as CHANNEL's new desktop_notification_sound setting, we should set it to default
|
||||||
|
if (userNotifyProps.desktop_notification_sound === savedChannelNotifyProps.desktop_notification_sound) {
|
||||||
|
channelNotifyProps.desktop_notification_sound = DesktopNotificationSounds.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new desktop_notification_sound setting as is
|
||||||
|
channelNotifyProps.desktop_notification_sound = savedChannelNotifyProps.desktop_notification_sound;
|
||||||
|
}
|
||||||
|
} else if (savedChannelNotifyProps.desktop_notification_sound === DesktopNotificationSounds.BING || savedChannelNotifyProps.desktop_notification_sound === DesktopNotificationSounds.DEFAULT) {
|
||||||
|
// If USER's desktop_notification_sound setting is not defined and CHANNEL's new desktop_notification_sound setting is either BING or DEFAULT, then save it as default
|
||||||
|
channelNotifyProps.desktop_notification_sound = DesktopNotificationSounds.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new desktop_notification_sound setting as is
|
||||||
|
channelNotifyProps.desktop_notification_sound = savedChannelNotifyProps.desktop_notification_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (savedChannelNotifyProps.push === userNotifyProps.push) {
|
||||||
|
channelNotifyProps.push = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
channelNotifyProps.push = savedChannelNotifyProps.push;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if USER's push_threads setting are defined
|
||||||
|
if (userNotifyProps?.push_threads?.length) {
|
||||||
|
// If USER's push_threads setting is same as CHANNEL's new push_threads setting, we should set it to default
|
||||||
|
if (userNotifyProps.push_threads === savedChannelNotifyProps.push_threads) {
|
||||||
|
channelNotifyProps.push_threads = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new push_threads setting as is
|
||||||
|
channelNotifyProps.push_threads = savedChannelNotifyProps.push_threads;
|
||||||
|
}
|
||||||
|
} else if (savedChannelNotifyProps.push_threads === NotificationLevels.MENTION || savedChannelNotifyProps.push_threads === NotificationLevels.DEFAULT) {
|
||||||
|
// If USER's push_threads setting is not defined and CHANNEL's new push_threads setting is MENTION or DEFAULT, then save it as default
|
||||||
|
channelNotifyProps.push_threads = NotificationLevels.DEFAULT;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's new push_threads setting as is
|
||||||
|
channelNotifyProps.push_threads = savedChannelNotifyProps.push_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If desktop and mobile settings are checked to be same, then same settings should be applied to push and push_threads
|
||||||
|
// as that of desktop and desktop_threads
|
||||||
|
if (desktopAndMobileSettingsDifferent === false) {
|
||||||
|
// If desktop is set to default, it means it is synced to the user's notification settings.
|
||||||
|
// Since we checked the box to use the same settings for mobile, we need to set channel's mobile to match channel's desktop.
|
||||||
|
// Setting mobile to default would sync it to the user's notification settings, which we want to avoid.
|
||||||
|
if (channelNotifyProps.desktop === NotificationLevels.DEFAULT) {
|
||||||
|
channelNotifyProps.push = userNotifyProps.desktop;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we should use the CHANNEL's desktop setting as is to match mobile settings
|
||||||
|
channelNotifyProps.push = channelNotifyProps.desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelNotifyProps.desktop_threads === NotificationLevels.DEFAULT) {
|
||||||
|
channelNotifyProps.push_threads = userNotifyProps.desktop_threads;
|
||||||
|
} else {
|
||||||
|
channelNotifyProps.push_threads = channelNotifyProps.desktop_threads;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelNotifyProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check's if channel's notification settings for desktop and mobile are different
|
||||||
|
*/
|
||||||
|
export function areDesktopAndMobileSettingsDifferent(
|
||||||
|
isCollapsedThreadsEnabled: boolean,
|
||||||
|
desktop: UserNotifyProps['desktop'],
|
||||||
|
desktopThreads: UserNotifyProps['desktop_threads'],
|
||||||
|
push?: UserNotifyProps['push'],
|
||||||
|
pushThreads?: UserNotifyProps['push_threads'],
|
||||||
|
): boolean {
|
||||||
|
if (push === NotificationLevels.DEFAULT || push === desktop) {
|
||||||
|
return isCollapsedThreadsEnabled && desktopThreads !== pushThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`ResetToDefaultButton should render if section name is valid 1`] = `
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
class="channel-notifications-settings-modal__reset-btn"
|
||||||
|
data-testid="resetToDefaultButton-desktop"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="icon icon-refresh"
|
||||||
|
/>
|
||||||
|
Reset to default
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -0,0 +1,173 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import type {ChannelMembership} from '@mattermost/types/channels';
|
||||||
|
import type {UserNotifyProps} from '@mattermost/types/users';
|
||||||
|
|
||||||
|
import {renderWithContext, screen} from 'tests/react_testing_utils';
|
||||||
|
import {NotificationLevels, DesktopSound} from 'utils/constants';
|
||||||
|
import {notificationSoundKeys, convertDesktopSoundNotifyPropFromUserToDesktop} from 'utils/notification_sounds';
|
||||||
|
import {TestHelper} from 'utils/test_helper';
|
||||||
|
|
||||||
|
import ResetToDefaultButton, {SectionName} from './index';
|
||||||
|
import type {Props} from './index';
|
||||||
|
|
||||||
|
describe('ResetToDefaultButton', () => {
|
||||||
|
const defaultProps: Props = {
|
||||||
|
sectionName: SectionName.Desktop,
|
||||||
|
userNotifyProps: TestHelper.getUserMock().notify_props,
|
||||||
|
userSelectedChannelNotifyProps: TestHelper.getChannelMembershipMock({}).notify_props,
|
||||||
|
onClick: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
test('should not show if section name is not valid', () => {
|
||||||
|
// Mock console.error to suppress PropTypes warning
|
||||||
|
const originalError = console.error;
|
||||||
|
console.error = jest.fn();
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
...defaultProps,
|
||||||
|
sectionName: 'invalidSectionName' as any,
|
||||||
|
};
|
||||||
|
|
||||||
|
const {container} = renderWithContext(<ResetToDefaultButton {...props}/>);
|
||||||
|
expect(container).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
console.error = originalError;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render if section name is valid', () => {
|
||||||
|
const {container} = renderWithContext(<ResetToDefaultButton {...defaultProps}/>);
|
||||||
|
expect(container).not.toBeEmptyDOMElement();
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show if desktop notifications are same as default user notification settings', () => {
|
||||||
|
const props = {
|
||||||
|
...defaultProps,
|
||||||
|
userNotifyProps: {
|
||||||
|
...defaultProps.userNotifyProps,
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
desktop_sound: 'true' as UserNotifyProps['desktop_sound'],
|
||||||
|
desktop_notification_sound: notificationSoundKeys[0] as UserNotifyProps['desktop_notification_sound'],
|
||||||
|
},
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
desktop_sound: DesktopSound.ON,
|
||||||
|
desktop_notification_sound: notificationSoundKeys[0] as ChannelMembership['notify_props']['desktop_notification_sound'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const {container} = renderWithContext(<ResetToDefaultButton {...props}/>);
|
||||||
|
expect(container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show if desktop notifications are not same as user notification settings', () => {
|
||||||
|
const props1 = {
|
||||||
|
...defaultProps,
|
||||||
|
userNotifyProps: {
|
||||||
|
...defaultProps.userNotifyProps,
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
desktop_sound: 'true' as UserNotifyProps['desktop_sound'],
|
||||||
|
desktop_notification_sound: notificationSoundKeys[0] as UserNotifyProps['desktop_notification_sound'],
|
||||||
|
},
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
desktop: NotificationLevels.MENTION,
|
||||||
|
desktop_threads: NotificationLevels.ALL,
|
||||||
|
desktop_sound: DesktopSound.ON,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const {rerender} = renderWithContext(<ResetToDefaultButton {...props1}/>);
|
||||||
|
expect(screen.getByText('Reset to default')).toBeInTheDocument();
|
||||||
|
|
||||||
|
const props2 = {
|
||||||
|
...props1,
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
desktop: NotificationLevels.ALL,
|
||||||
|
desktop_sound: DesktopSound.OFF,
|
||||||
|
desktop_notification_sound: notificationSoundKeys[0] as UserNotifyProps['desktop_notification_sound'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rerender(<ResetToDefaultButton {...props2}/>);
|
||||||
|
expect(screen.getByText('Reset to default')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not show if mobile notifications are same as default user notification settings', () => {
|
||||||
|
const props = {
|
||||||
|
...defaultProps,
|
||||||
|
sectionName: SectionName.Mobile,
|
||||||
|
userNotifyProps: {
|
||||||
|
...defaultProps.userNotifyProps,
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
},
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const {container} = renderWithContext(<ResetToDefaultButton {...props}/>);
|
||||||
|
expect(container).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should show if mobile notifications are not same as user notification settings', () => {
|
||||||
|
const props = {
|
||||||
|
...defaultProps,
|
||||||
|
sectionName: SectionName.Mobile,
|
||||||
|
userNotifyProps: {
|
||||||
|
...defaultProps.userNotifyProps,
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
},
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
push: NotificationLevels.MENTION,
|
||||||
|
push_threads: NotificationLevels.ALL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const {rerender} = renderWithContext(<ResetToDefaultButton {...props}/>);
|
||||||
|
expect(screen.getByText('Reset to default')).toBeInTheDocument();
|
||||||
|
|
||||||
|
const props2 = {
|
||||||
|
...defaultProps,
|
||||||
|
userSelectedChannelNotifyProps: {
|
||||||
|
...defaultProps.userSelectedChannelNotifyProps,
|
||||||
|
push: NotificationLevels.ALL,
|
||||||
|
push_threads: NotificationLevels.MENTION,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rerender(<ResetToDefaultButton {...props2}/>);
|
||||||
|
expect(screen.getByText('Reset to default')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('convertDesktopSoundNotifyPropFromUserToDesktop', () => {
|
||||||
|
test('should return ON if user desktop sound is true', () => {
|
||||||
|
const desktopSound = convertDesktopSoundNotifyPropFromUserToDesktop('true');
|
||||||
|
expect(desktopSound).toBe(DesktopSound.ON);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return ON if user desktop sound is not present', () => {
|
||||||
|
const desktopSound = convertDesktopSoundNotifyPropFromUserToDesktop();
|
||||||
|
expect(desktopSound).toBe(DesktopSound.ON);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return OFF if user desktop sound is false', () => {
|
||||||
|
const desktopSound = convertDesktopSoundNotifyPropFromUserToDesktop('false');
|
||||||
|
expect(desktopSound).toBe(DesktopSound.OFF);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React, {useMemo} from 'react';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import type {ChannelMembership, ChannelNotifyProps} from '@mattermost/types/channels';
|
||||||
|
import type {UserNotifyProps, UserProfile} from '@mattermost/types/users';
|
||||||
|
|
||||||
|
import {DesktopSound, NotificationLevels} from 'utils/constants';
|
||||||
|
import {notificationSoundKeys, convertDesktopSoundNotifyPropFromUserToDesktop} from 'utils/notification_sounds';
|
||||||
|
|
||||||
|
export enum SectionName {
|
||||||
|
Desktop = 'desktop',
|
||||||
|
Mobile = 'mobile',
|
||||||
|
}
|
||||||
|
|
||||||
|
const VALID_SECTION_NAMES = Object.values(SectionName);
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
sectionName: SectionName;
|
||||||
|
userNotifyProps: UserProfile['notify_props'];
|
||||||
|
|
||||||
|
/** The user's selected channel notify props which is not yet saved */
|
||||||
|
userSelectedChannelNotifyProps: ChannelMembership['notify_props'];
|
||||||
|
onClick: (channelNotifyPropsDefaultedToUserNotifyProps: ChannelMembership['notify_props'], sectionName: SectionName) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ResetToDefaultButton(props: Props) {
|
||||||
|
const areDesktopNotificationsSameAsDefault = useMemo(() => {
|
||||||
|
const isNotifyMeAboutSame = props.userNotifyProps.desktop === props.userSelectedChannelNotifyProps.desktop;
|
||||||
|
const isThreadReplyNotificationsSame = props.userNotifyProps.desktop_threads === props.userSelectedChannelNotifyProps.desktop_threads;
|
||||||
|
const isSoundSame = convertDesktopSoundNotifyPropFromUserToDesktop(props.userNotifyProps.desktop_sound) === props.userSelectedChannelNotifyProps.desktop_sound;
|
||||||
|
|
||||||
|
let isNotificationSoundSame = false;
|
||||||
|
if (props.userNotifyProps.desktop_notification_sound) {
|
||||||
|
isNotificationSoundSame = props.userNotifyProps.desktop_notification_sound === props.userSelectedChannelNotifyProps.desktop_notification_sound;
|
||||||
|
} else {
|
||||||
|
// It could happen that the notification sound is not set in the user's notify props. That case we should assume its the Bing sound.
|
||||||
|
isNotificationSoundSame = props.userSelectedChannelNotifyProps.desktop_notification_sound === notificationSoundKeys[0] as ChannelNotifyProps['desktop_notification_sound'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return isNotifyMeAboutSame && isThreadReplyNotificationsSame && isSoundSame && isNotificationSoundSame;
|
||||||
|
}, [
|
||||||
|
props.userNotifyProps.desktop,
|
||||||
|
props.userSelectedChannelNotifyProps.desktop,
|
||||||
|
props.userNotifyProps.desktop_threads,
|
||||||
|
props.userSelectedChannelNotifyProps.desktop_threads,
|
||||||
|
props.userNotifyProps.desktop_sound,
|
||||||
|
props.userSelectedChannelNotifyProps.desktop_sound,
|
||||||
|
props.userNotifyProps.desktop_notification_sound,
|
||||||
|
props.userSelectedChannelNotifyProps.desktop_notification_sound,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const areMobileNotificationsSameAsDefault = useMemo(() => {
|
||||||
|
const isNotifyMeAboutSame = props.userNotifyProps.push === props.userSelectedChannelNotifyProps.push;
|
||||||
|
const isThreadReplyNotificationsSame = props.userNotifyProps.push_threads === props.userSelectedChannelNotifyProps.push_threads;
|
||||||
|
|
||||||
|
return isNotifyMeAboutSame && isThreadReplyNotificationsSame;
|
||||||
|
}, [
|
||||||
|
props.userNotifyProps.push,
|
||||||
|
props.userSelectedChannelNotifyProps.push,
|
||||||
|
props.userNotifyProps.push_threads,
|
||||||
|
props.userSelectedChannelNotifyProps.push_threads,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!VALID_SECTION_NAMES.includes(props.sectionName)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.sectionName === SectionName.Desktop && areDesktopNotificationsSameAsDefault) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.sectionName === SectionName.Mobile && areMobileNotificationsSameAsDefault) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOnClick() {
|
||||||
|
const channelNotifyPropsDefaultedToUserNotifyProps = resetChannelsNotificationToUsersDefault(props.userNotifyProps, props.sectionName);
|
||||||
|
props.onClick(channelNotifyPropsDefaultedToUserNotifyProps, props.sectionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className='channel-notifications-settings-modal__reset-btn'
|
||||||
|
onClick={handleOnClick}
|
||||||
|
data-testid={`resetToDefaultButton-${props.sectionName}`}
|
||||||
|
>
|
||||||
|
<i className='icon icon-refresh'/>
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.resetToDefault'
|
||||||
|
defaultMessage='Reset to default'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetChannelsNotificationToUsersDefault(userNotifyProps: UserNotifyProps, sectionName: SectionName): ChannelMembership['notify_props'] {
|
||||||
|
if (sectionName === SectionName.Desktop) {
|
||||||
|
return {
|
||||||
|
desktop: userNotifyProps.desktop,
|
||||||
|
desktop_threads: userNotifyProps?.desktop_threads ?? NotificationLevels.ALL,
|
||||||
|
desktop_sound: userNotifyProps && userNotifyProps.desktop_sound ? convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyProps.desktop_sound) : DesktopSound.ON,
|
||||||
|
desktop_notification_sound: userNotifyProps?.desktop_notification_sound ?? notificationSoundKeys[0] as ChannelNotifyProps['desktop_notification_sound'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionName === SectionName.Mobile) {
|
||||||
|
return {
|
||||||
|
push: userNotifyProps.push,
|
||||||
|
push_threads: userNotifyProps?.push_threads ?? NotificationLevels.ALL,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
@ -4,18 +4,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import type {ChannelNotifyProps} from '@mattermost/types/channels';
|
|
||||||
import type {UserNotifyProps} from '@mattermost/types/users';
|
|
||||||
|
|
||||||
import type {FieldsetCheckbox} from 'components/widgets/modals/components/checkbox_setting_item';
|
import type {FieldsetCheckbox} from 'components/widgets/modals/components/checkbox_setting_item';
|
||||||
import type {FieldsetRadio} from 'components/widgets/modals/components/radio_setting_item';
|
import type {FieldsetRadio} from 'components/widgets/modals/components/radio_setting_item';
|
||||||
import type {FieldsetReactSelect} from 'components/widgets/modals/components/react_select_item';
|
import type {FieldsetReactSelect} from 'components/widgets/modals/components/react_select_item';
|
||||||
|
|
||||||
import {DesktopSound, NotificationLevels} from 'utils/constants';
|
import {NotificationLevels} from 'utils/constants';
|
||||||
import {optionsOfMessageNotificationSoundsSelect} from 'utils/notification_sounds';
|
import {optionsOfMessageNotificationSoundsSelect} from 'utils/notification_sounds';
|
||||||
|
|
||||||
export type ChannelMemberNotifyProps = Partial<ChannelNotifyProps> & Pick<UserNotifyProps, 'desktop_threads' | 'push_threads'>
|
|
||||||
|
|
||||||
const MuteChannelInputFieldData: FieldsetCheckbox = {
|
const MuteChannelInputFieldData: FieldsetCheckbox = {
|
||||||
name: 'mute channel',
|
name: 'mute channel',
|
||||||
dataTestId: 'muteChannel',
|
dataTestId: 'muteChannel',
|
||||||
@ -53,52 +48,58 @@ export const desktopNotificationInputFieldData = (defaultOption: string): Fields
|
|||||||
dataTestId: `desktopNotification-${NotificationLevels.ALL}`,
|
dataTestId: `desktopNotification-${NotificationLevels.ALL}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.desktopNotificationAllLabel'
|
id='channelNotifications.desktopNotification.allMessages'
|
||||||
defaultMessage='All new messages'
|
defaultMessage='All new messages {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.ALL ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `desktopNotification-${NotificationLevels.ALL}`,
|
name: `desktopNotification-${NotificationLevels.ALL}`,
|
||||||
key: `desktopNotification-${NotificationLevels.ALL}`,
|
key: `desktopNotification-${NotificationLevels.ALL}`,
|
||||||
value: NotificationLevels.ALL,
|
value: NotificationLevels.ALL,
|
||||||
suffix: defaultOption === NotificationLevels.ALL ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataTestId: `desktopNotification-${NotificationLevels.MENTION}`,
|
dataTestId: `desktopNotification-${NotificationLevels.MENTION}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.desktopNotificationMentionLabel'
|
id='channelNotifications.desktopNotification.mention'
|
||||||
defaultMessage='Mentions, direct messages, and keywords only'
|
defaultMessage='Mentions, direct messages, and keywords only {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.MENTION ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `desktopNotification-${NotificationLevels.MENTION}`,
|
name: `desktopNotification-${NotificationLevels.MENTION}`,
|
||||||
key: `desktopNotification-${NotificationLevels.MENTION}`,
|
key: `desktopNotification-${NotificationLevels.MENTION}`,
|
||||||
value: NotificationLevels.MENTION,
|
value: NotificationLevels.MENTION,
|
||||||
suffix: defaultOption === NotificationLevels.MENTION ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataTestId: `desktopNotification-${NotificationLevels.NONE}`,
|
dataTestId: `desktopNotification-${NotificationLevels.NONE}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.desktopNotificationNothingLabel'
|
id='channelNotifications.desktopNotification.nothing'
|
||||||
defaultMessage='Nothing'
|
defaultMessage='Nothing {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.NONE ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `desktopNotification-${NotificationLevels.NONE}`,
|
name: `desktopNotification-${NotificationLevels.NONE}`,
|
||||||
key: `desktopNotification-${NotificationLevels.NONE}`,
|
key: `desktopNotification-${NotificationLevels.NONE}`,
|
||||||
value: NotificationLevels.NONE,
|
value: NotificationLevels.NONE,
|
||||||
suffix: defaultOption === NotificationLevels.NONE ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -122,74 +123,64 @@ export const mobileNotificationInputFieldData = (defaultOption: string): Fieldse
|
|||||||
dataTestId: `MobileNotification-${NotificationLevels.ALL}`,
|
dataTestId: `MobileNotification-${NotificationLevels.ALL}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.MobileNotificationAllLabel'
|
id='channelNotifications.mobileNotification.newMessages'
|
||||||
defaultMessage='All new messages'
|
defaultMessage='All new messages {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.ALL ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `MobileNotification-${NotificationLevels.ALL}`,
|
name: `MobileNotification-${NotificationLevels.ALL}`,
|
||||||
key: `MobileNotification-${NotificationLevels.ALL}`,
|
key: `MobileNotification-${NotificationLevels.ALL}`,
|
||||||
value: NotificationLevels.ALL,
|
value: NotificationLevels.ALL,
|
||||||
suffix: defaultOption === NotificationLevels.ALL ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataTestId: `MobileNotification-${NotificationLevels.MENTION}`,
|
dataTestId: `MobileNotification-${NotificationLevels.MENTION}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.MobileNotificationMentionLabel'
|
id='channelNotifications.mobileNotification.mention'
|
||||||
defaultMessage='Mentions, direct messages, and keywords only'
|
defaultMessage='Mentions, direct messages, and keywords only {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.MENTION ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `MobileNotification-${NotificationLevels.MENTION}`,
|
name: `MobileNotification-${NotificationLevels.MENTION}`,
|
||||||
key: `MobileNotification-${NotificationLevels.MENTION}`,
|
key: `MobileNotification-${NotificationLevels.MENTION}`,
|
||||||
value: NotificationLevels.MENTION,
|
value: NotificationLevels.MENTION,
|
||||||
suffix: defaultOption === NotificationLevels.MENTION ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataTestId: `MobileNotification-${NotificationLevels.NONE}`,
|
dataTestId: `MobileNotification-${NotificationLevels.NONE}`,
|
||||||
title: (
|
title: (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='channel_notifications.MobileNotificationNothingLabel'
|
id='channelNotifications.mobileNotification.nothing'
|
||||||
defaultMessage='Nothing'
|
defaultMessage='Nothing {optionalDefault}'
|
||||||
|
values={{
|
||||||
|
optionalDefault: defaultOption === NotificationLevels.NONE ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_notifications.default'
|
||||||
|
defaultMessage='(default)'
|
||||||
|
/>) : undefined,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
name: `MobileNotification-${NotificationLevels.NONE}`,
|
name: `MobileNotification-${NotificationLevels.NONE}`,
|
||||||
key: `MobileNotification-${NotificationLevels.NONE}`,
|
key: `MobileNotification-${NotificationLevels.NONE}`,
|
||||||
value: NotificationLevels.NONE,
|
value: NotificationLevels.NONE,
|
||||||
suffix: defaultOption === NotificationLevels.NONE ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_notifications.default'
|
|
||||||
defaultMessage='(default)'
|
|
||||||
/>) : undefined,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
export default {
|
||||||
* This conversion is needed because User's preference for desktop sound is stored as either true or false. On the other hand,
|
|
||||||
* Channel's specific desktop sound is stored as either On or Off.
|
|
||||||
*/
|
|
||||||
export function convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyDesktopSound?: UserNotifyProps['desktop_sound']) {
|
|
||||||
if (!userNotifyDesktopSound) {
|
|
||||||
return DesktopSound.OFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userNotifyDesktopSound === 'true') {
|
|
||||||
return DesktopSound.ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DesktopSound.ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
const utils = {
|
|
||||||
desktopNotificationInputFieldData,
|
desktopNotificationInputFieldData,
|
||||||
desktopNotificationSoundsCheckboxFieldData,
|
desktopNotificationSoundsCheckboxFieldData,
|
||||||
desktopNotificationSoundsSelectFieldData,
|
desktopNotificationSoundsSelectFieldData,
|
||||||
@ -201,5 +192,3 @@ const utils = {
|
|||||||
AutoFollowThreadsInputFieldData,
|
AutoFollowThreadsInputFieldData,
|
||||||
sameMobileSettingsDesktopInputFieldData,
|
sameMobileSettingsDesktopInputFieldData,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default utils;
|
|
||||||
|
@ -429,7 +429,7 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleChangeForCustomKeysWithHightlightInput = (values: ValueType<{ value: string }>) => {
|
handleChangeForCustomKeysWithHighlightInput = (values: ValueType<{ value: string }>) => {
|
||||||
if (values && Array.isArray(values) && values.length > 0) {
|
if (values && Array.isArray(values) && values.length > 0) {
|
||||||
const customKeysWithHighlight = values.
|
const customKeysWithHighlight = values.
|
||||||
map((value: MultiInputValue) => {
|
map((value: MultiInputValue) => {
|
||||||
@ -682,7 +682,7 @@ class NotificationsTab extends React.PureComponent<Props, State> {
|
|||||||
MenuList: () => null,
|
MenuList: () => null,
|
||||||
}}
|
}}
|
||||||
aria-labelledby='mentionKeysWithHighlightInput'
|
aria-labelledby='mentionKeysWithHighlightInput'
|
||||||
onChange={this.handleChangeForCustomKeysWithHightlightInput}
|
onChange={this.handleChangeForCustomKeysWithHighlightInput}
|
||||||
value={this.state.customKeysWithHighlight}
|
value={this.state.customKeysWithHighlight}
|
||||||
inputValue={this.state.customKeysWithHighlightInputValue}
|
inputValue={this.state.customKeysWithHighlightInputValue}
|
||||||
onInputChange={this.handleChangeForCustomKeysWithHighlightInputValue}
|
onInputChange={this.handleChangeForCustomKeysWithHighlightInputValue}
|
||||||
@ -1142,9 +1142,12 @@ const customKeywordsSelectorStyles: ReactSelectStyles = {
|
|||||||
|
|
||||||
const validNotificationLevels = Object.values(NotificationLevels);
|
const validNotificationLevels = Object.values(NotificationLevels);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check's if user's global notification settings for desktop and mobile are different
|
||||||
|
*/
|
||||||
export function areDesktopAndMobileSettingsDifferent(
|
export function areDesktopAndMobileSettingsDifferent(
|
||||||
desktopActivity: UserNotifyProps['desktop'],
|
desktopActivity: UserNotifyProps['desktop'],
|
||||||
pushActivity: UserNotifyProps['push'],
|
pushActivity?: UserNotifyProps['push'],
|
||||||
desktopThreads?: UserNotifyProps['desktop_threads'],
|
desktopThreads?: UserNotifyProps['desktop_threads'],
|
||||||
pushThreads?: UserNotifyProps['push_threads'],
|
pushThreads?: UserNotifyProps['push_threads'],
|
||||||
isCollapsedThreadsEnabled?: boolean,
|
isCollapsedThreadsEnabled?: boolean,
|
||||||
|
@ -19,6 +19,7 @@ export type BaseSettingItemProps = {
|
|||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
error?: ExtendedMessageDescriptor;
|
error?: ExtendedMessageDescriptor;
|
||||||
|
dataTestId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = BaseSettingItemProps & {
|
type Props = BaseSettingItemProps & {
|
||||||
@ -28,7 +29,7 @@ type Props = BaseSettingItemProps & {
|
|||||||
descriptionAboveContent?: boolean;
|
descriptionAboveContent?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BaseSettingItem({title, description, content, className, error, descriptionAboveContent = false, isContentInline = false}: Props): JSX.Element {
|
function BaseSettingItem({title, description, content, className, error, descriptionAboveContent = false, isContentInline = false, dataTestId}: Props): JSX.Element {
|
||||||
const {formatMessage} = useIntl();
|
const {formatMessage} = useIntl();
|
||||||
|
|
||||||
const titleComponent = title && (
|
const titleComponent = title && (
|
||||||
@ -60,7 +61,10 @@ function BaseSettingItem({title, description, content, className, error, descrip
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('mm-modal-generic-section-item', className)}>
|
<div
|
||||||
|
data-testid={dataTestId}
|
||||||
|
className={classNames('mm-modal-generic-section-item', className)}
|
||||||
|
>
|
||||||
{titleComponent}
|
{titleComponent}
|
||||||
{descriptionAboveContent ? descriptionComponent : undefined}
|
{descriptionAboveContent ? descriptionComponent : undefined}
|
||||||
<div
|
<div
|
||||||
|
@ -33,6 +33,7 @@ export default function CheckboxSettingItem({
|
|||||||
inputFieldTitle,
|
inputFieldTitle,
|
||||||
handleChange,
|
handleChange,
|
||||||
className,
|
className,
|
||||||
|
dataTestId,
|
||||||
descriptionAboveContent = false,
|
descriptionAboveContent = false,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const content = (
|
const content = (
|
||||||
@ -59,6 +60,7 @@ export default function CheckboxSettingItem({
|
|||||||
content={content}
|
content={content}
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
|
dataTestId={dataTestId}
|
||||||
className={className}
|
className={className}
|
||||||
descriptionAboveContent={descriptionAboveContent}
|
descriptionAboveContent={descriptionAboveContent}
|
||||||
/>
|
/>
|
||||||
|
@ -14,7 +14,6 @@ export type FieldsetRadio = {
|
|||||||
name: string;
|
name: string;
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
suffix?: JSX.Element;
|
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +31,7 @@ function RadioSettingItem({
|
|||||||
inputFieldData,
|
inputFieldData,
|
||||||
inputFieldValue,
|
inputFieldValue,
|
||||||
handleChange,
|
handleChange,
|
||||||
|
dataTestId,
|
||||||
}: Props): JSX.Element {
|
}: Props): JSX.Element {
|
||||||
const fields = inputFieldData.options.map((option) => {
|
const fields = inputFieldData.options.map((option) => {
|
||||||
return (
|
return (
|
||||||
@ -49,7 +49,6 @@ function RadioSettingItem({
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
{option.title}
|
{option.title}
|
||||||
{option.suffix}
|
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -61,6 +60,7 @@ function RadioSettingItem({
|
|||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<BaseSettingItem
|
<BaseSettingItem
|
||||||
|
dataTestId={dataTestId}
|
||||||
className={className}
|
className={className}
|
||||||
content={content}
|
content={content}
|
||||||
title={title}
|
title={title}
|
||||||
|
@ -3202,9 +3202,6 @@
|
|||||||
"channel_notifications.checkbox.sameMobileSettingsDesktop": "Use the same notification settings as desktop",
|
"channel_notifications.checkbox.sameMobileSettingsDesktop": "Use the same notification settings as desktop",
|
||||||
"channel_notifications.checkbox.threadsReplyTitle": "Notify me about replies to threads I’m following",
|
"channel_notifications.checkbox.threadsReplyTitle": "Notify me about replies to threads I’m following",
|
||||||
"channel_notifications.default": "(default)",
|
"channel_notifications.default": "(default)",
|
||||||
"channel_notifications.desktopNotificationAllLabel": "All new messages",
|
|
||||||
"channel_notifications.desktopNotificationMentionLabel": "Mentions, direct messages, and keywords only",
|
|
||||||
"channel_notifications.desktopNotificationNothingLabel": "Nothing",
|
|
||||||
"channel_notifications.desktopNotifications.soundEnable": "Message notification sounds",
|
"channel_notifications.desktopNotifications.soundEnable": "Message notification sounds",
|
||||||
"channel_notifications.desktopNotifications.soundSelectPlaceholder": "Select a sound",
|
"channel_notifications.desktopNotifications.soundSelectPlaceholder": "Select a sound",
|
||||||
"channel_notifications.desktopNotifications.title": "Sounds",
|
"channel_notifications.desktopNotifications.title": "Sounds",
|
||||||
@ -3213,9 +3210,6 @@
|
|||||||
"channel_notifications.ignoreMentionsDesc": "When enabled, @channel, @here and @all will not trigger mentions or mention notifications in this channel",
|
"channel_notifications.ignoreMentionsDesc": "When enabled, @channel, @here and @all will not trigger mentions or mention notifications in this channel",
|
||||||
"channel_notifications.ignoreMentionsTitle": "Ignore mentions for @channel, @here and @all",
|
"channel_notifications.ignoreMentionsTitle": "Ignore mentions for @channel, @here and @all",
|
||||||
"channel_notifications.levels.all": "All",
|
"channel_notifications.levels.all": "All",
|
||||||
"channel_notifications.MobileNotificationAllLabel": "All new messages",
|
|
||||||
"channel_notifications.MobileNotificationMentionLabel": "Mentions, direct messages, and keywords only",
|
|
||||||
"channel_notifications.MobileNotificationNothingLabel": "Nothing",
|
|
||||||
"channel_notifications.mobileNotificationsDesc": "Notification alerts are pushed to your mobile device when there is activity in Mattermost.",
|
"channel_notifications.mobileNotificationsDesc": "Notification alerts are pushed to your mobile device when there is activity in Mattermost.",
|
||||||
"channel_notifications.mobileNotificationsTitle": "Mobile Notifications",
|
"channel_notifications.mobileNotificationsTitle": "Mobile Notifications",
|
||||||
"channel_notifications.muteAndIgnore": "Mute or ignore",
|
"channel_notifications.muteAndIgnore": "Mute or ignore",
|
||||||
@ -3234,6 +3228,12 @@
|
|||||||
"channelHeader.removeFromFavorites": "Remove from Favorites",
|
"channelHeader.removeFromFavorites": "Remove from Favorites",
|
||||||
"channelHeader.unmute": "Unmute",
|
"channelHeader.unmute": "Unmute",
|
||||||
"channelHeader.viewInfo": "View Info",
|
"channelHeader.viewInfo": "View Info",
|
||||||
|
"channelNotifications.desktopNotification.allMessages": "All new messages {optionalDefault}",
|
||||||
|
"channelNotifications.desktopNotification.mention": "Mentions, direct messages, and keywords only {optionalDefault}",
|
||||||
|
"channelNotifications.desktopNotification.nothing": "Nothing {optionalDefault}",
|
||||||
|
"channelNotifications.mobileNotification.mention": "Mentions, direct messages, and keywords only {optionalDefault}",
|
||||||
|
"channelNotifications.mobileNotification.newMessages": "All new messages {optionalDefault}",
|
||||||
|
"channelNotifications.mobileNotification.nothing": "Nothing {optionalDefault}",
|
||||||
"channelView.login.successfull": "Login Successful",
|
"channelView.login.successfull": "Login Successful",
|
||||||
"claim.email_to_ldap.enterLdapPwd": "Enter the ID and password for your AD/LDAP account",
|
"claim.email_to_ldap.enterLdapPwd": "Enter the ID and password for your AD/LDAP account",
|
||||||
"claim.email_to_ldap.enterPwd": "Enter the password for your {site} email account",
|
"claim.email_to_ldap.enterPwd": "Enter the password for your {site} email account",
|
||||||
|
@ -990,6 +990,7 @@ export const NotificationLevels = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const DesktopSound = {
|
export const DesktopSound = {
|
||||||
|
DEFAULT: 'default',
|
||||||
ON: 'on',
|
ON: 'on',
|
||||||
OFF: 'off',
|
OFF: 'off',
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -5,6 +5,9 @@ import type {ReactNode} from 'react';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import type {ChannelNotifyProps} from '@mattermost/types/channels';
|
||||||
|
import type {UserNotifyProps} from '@mattermost/types/users';
|
||||||
|
|
||||||
import bing from 'sounds/bing.mp3';
|
import bing from 'sounds/bing.mp3';
|
||||||
import calls_calm from 'sounds/calls_calm.mp3';
|
import calls_calm from 'sounds/calls_calm.mp3';
|
||||||
import calls_cheerful from 'sounds/calls_cheerful.mp3';
|
import calls_cheerful from 'sounds/calls_cheerful.mp3';
|
||||||
@ -15,21 +18,32 @@ import down from 'sounds/down.mp3';
|
|||||||
import hello from 'sounds/hello.mp3';
|
import hello from 'sounds/hello.mp3';
|
||||||
import ripple from 'sounds/ripple.mp3';
|
import ripple from 'sounds/ripple.mp3';
|
||||||
import upstairs from 'sounds/upstairs.mp3';
|
import upstairs from 'sounds/upstairs.mp3';
|
||||||
|
import {DesktopSound} from 'utils/constants';
|
||||||
import * as UserAgent from 'utils/user_agent';
|
import * as UserAgent from 'utils/user_agent';
|
||||||
|
|
||||||
export const notificationSounds = new Map([
|
export const DesktopNotificationSounds = {
|
||||||
['Bing', bing],
|
DEFAULT: 'default',
|
||||||
['Crackle', crackle],
|
BING: 'Bing',
|
||||||
['Down', down],
|
CRACKLE: 'Crackle',
|
||||||
['Hello', hello],
|
DOWN: 'Down',
|
||||||
['Ripple', ripple],
|
HELLO: 'Hello',
|
||||||
['Upstairs', upstairs],
|
RIPPLE: 'Ripple',
|
||||||
|
UPSTAIRS: 'Upstairs',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const notificationSounds = new Map<string, string>([
|
||||||
|
[DesktopNotificationSounds.BING, bing],
|
||||||
|
[DesktopNotificationSounds.CRACKLE, crackle],
|
||||||
|
[DesktopNotificationSounds.DOWN, down],
|
||||||
|
[DesktopNotificationSounds.HELLO, hello],
|
||||||
|
[DesktopNotificationSounds.RIPPLE, ripple],
|
||||||
|
[DesktopNotificationSounds.UPSTAIRS, upstairs],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const notificationSoundKeys = Array.from(notificationSounds.keys());
|
export const notificationSoundKeys = Array.from(notificationSounds.keys());
|
||||||
|
|
||||||
export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; label: ReactNode}> = notificationSoundKeys.map((soundName) => {
|
export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; label: ReactNode}> = notificationSoundKeys.map((soundName) => {
|
||||||
if (soundName === 'Bing') {
|
if (soundName === DesktopNotificationSounds.BING) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -39,7 +53,7 @@ export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; lab
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else if (soundName === 'Crackle') {
|
} else if (soundName === DesktopNotificationSounds.CRACKLE) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -49,7 +63,7 @@ export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; lab
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else if (soundName === 'Down') {
|
} else if (soundName === DesktopNotificationSounds.DOWN) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -59,7 +73,7 @@ export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; lab
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else if (soundName === 'Hello') {
|
} else if (soundName === DesktopNotificationSounds.HELLO) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -69,7 +83,7 @@ export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; lab
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else if (soundName === 'Ripple') {
|
} else if (soundName === DesktopNotificationSounds.RIPPLE) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -79,7 +93,7 @@ export const optionsOfMessageNotificationSoundsSelect: Array<{value: string; lab
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
} else if (soundName === 'Upstairs') {
|
} else if (soundName === DesktopNotificationSounds.UPSTAIRS) {
|
||||||
return {
|
return {
|
||||||
value: soundName,
|
value: soundName,
|
||||||
label: (
|
label: (
|
||||||
@ -249,3 +263,15 @@ export function loopNotificationRing(name: string) {
|
|||||||
export function hasSoundOptions() {
|
export function hasSoundOptions() {
|
||||||
return (!UserAgent.isEdge());
|
return (!UserAgent.isEdge());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This conversion is needed because User's preference for desktop sound is stored as either true or false. On the other hand,
|
||||||
|
* Channel's specific desktop sound is stored as either On or Off.
|
||||||
|
*/
|
||||||
|
export function convertDesktopSoundNotifyPropFromUserToDesktop(userNotifyDesktopSound?: UserNotifyProps['desktop_sound']): ChannelNotifyProps['desktop_sound'] {
|
||||||
|
if (userNotifyDesktopSound && userNotifyDesktopSound === 'false') {
|
||||||
|
return DesktopSound.OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DesktopSound.ON;
|
||||||
|
}
|
||||||
|
@ -22,8 +22,8 @@ export type ChannelStats = {
|
|||||||
export type ChannelNotifyProps = {
|
export type ChannelNotifyProps = {
|
||||||
desktop_threads: 'default' | 'all' | 'mention' | 'none';
|
desktop_threads: 'default' | 'all' | 'mention' | 'none';
|
||||||
desktop: 'default' | 'all' | 'mention' | 'none';
|
desktop: 'default' | 'all' | 'mention' | 'none';
|
||||||
desktop_sound: 'on' | 'off';
|
desktop_sound: 'default' | 'on' | 'off';
|
||||||
desktop_notification_sound?: 'Bing' | 'Crackle' | 'Down' | 'Hello' | 'Ripple' | 'Upstairs';
|
desktop_notification_sound?: 'default' | 'Bing' | 'Crackle' | 'Down' | 'Hello' | 'Ripple' | 'Upstairs';
|
||||||
email: 'default' | 'all' | 'mention' | 'none';
|
email: 'default' | 'all' | 'mention' | 'none';
|
||||||
mark_unread: 'all' | 'mention';
|
mark_unread: 'all' | 'mention';
|
||||||
push: 'default' | 'all' | 'mention' | 'none';
|
push: 'default' | 'all' | 'mention' | 'none';
|
||||||
|
@ -10,7 +10,7 @@ import type {IDMappedObjects, RelationOneToManyUnique, RelationOneToOne} from '.
|
|||||||
|
|
||||||
export type UserNotifyProps = {
|
export type UserNotifyProps = {
|
||||||
desktop: 'default' | 'all' | 'mention' | 'none';
|
desktop: 'default' | 'all' | 'mention' | 'none';
|
||||||
desktop_sound: 'true' | 'false';
|
desktop_sound: 'default' | 'true' | 'false';
|
||||||
calls_desktop_sound: 'true' | 'false';
|
calls_desktop_sound: 'true' | 'false';
|
||||||
email: 'true' | 'false';
|
email: 'true' | 'false';
|
||||||
mark_unread: 'all' | 'mention';
|
mark_unread: 'all' | 'mention';
|
||||||
@ -21,7 +21,7 @@ export type UserNotifyProps = {
|
|||||||
channel: 'true' | 'false';
|
channel: 'true' | 'false';
|
||||||
mention_keys: string;
|
mention_keys: string;
|
||||||
highlight_keys: string;
|
highlight_keys: string;
|
||||||
desktop_notification_sound?: 'Bing' | 'Crackle' | 'Down' | 'Hello' | 'Ripple' | 'Upstairs';
|
desktop_notification_sound?: 'default' | 'Bing' | 'Crackle' | 'Down' | 'Hello' | 'Ripple' | 'Upstairs';
|
||||||
calls_notification_sound?: 'Dynamic' | 'Calm' | 'Urgent' | 'Cheerful';
|
calls_notification_sound?: 'Dynamic' | 'Calm' | 'Urgent' | 'Cheerful';
|
||||||
desktop_threads?: 'default' | 'all' | 'mention' | 'none';
|
desktop_threads?: 'default' | 'all' | 'mention' | 'none';
|
||||||
email_threads?: 'default' | 'all' | 'mention' | 'none';
|
email_threads?: 'default' | 'all' | 'mention' | 'none';
|
||||||
|
Loading…
Reference in New Issue
Block a user