Properly unset active channel in the server (#26846)
* Properly unset active channel in the server * Address feedback --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
69fe5c06e4
Коммит
c22509eca2
@@ -618,7 +618,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
|
|||||||
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
status = &model.Status{UserId: id, Status: model.StatusOffline, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusReason := DoesStatusAllowPushNotification(profileMap[id].NotifyProps, status, post.ChannelId); statusReason == "" {
|
if statusReason := DoesStatusAllowPushNotification(profileMap[id].NotifyProps, status, post.ChannelId, true); statusReason == "" {
|
||||||
a.sendPushNotification(
|
a.sendPushNotification(
|
||||||
notification,
|
notification,
|
||||||
profileMap[id],
|
profileMap[id],
|
||||||
|
|||||||
@@ -590,7 +590,7 @@ func (a *App) ShouldSendPushNotification(user *model.User, channelNotifyProps mo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if statusAllowedReason := DoesStatusAllowPushNotification(user.NotifyProps, status, post.ChannelId); statusAllowedReason != "" {
|
if statusAllowedReason := DoesStatusAllowPushNotification(user.NotifyProps, status, post.ChannelId, false); statusAllowedReason != "" {
|
||||||
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusAllowedReason)
|
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusAllowedReason)
|
||||||
a.NotificationsLog().Debug("Notification not sent - status",
|
a.NotificationsLog().Debug("Notification not sent - status",
|
||||||
mlog.String("type", model.NotificationTypePush),
|
mlog.String("type", model.NotificationTypePush),
|
||||||
@@ -648,14 +648,18 @@ func DoesNotifyPropsAllowPushNotification(user *model.User, channelNotifyProps m
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoesStatusAllowPushNotification(userNotifyProps model.StringMap, status *model.Status, channelID string) model.NotificationReason {
|
func DoesStatusAllowPushNotification(userNotifyProps model.StringMap, status *model.Status, channelID string, isCRT bool) model.NotificationReason {
|
||||||
// If User status is DND or OOO return false right away
|
// If User status is DND or OOO return false right away
|
||||||
if status.Status == model.StatusDnd || status.Status == model.StatusOutOfOffice {
|
if status.Status == model.StatusDnd || status.Status == model.StatusOutOfOffice {
|
||||||
return model.NotificationReasonUserStatus
|
return model.NotificationReasonUserStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
pushStatus, ok := userNotifyProps[model.PushStatusNotifyProp]
|
pushStatus, ok := userNotifyProps[model.PushStatusNotifyProp]
|
||||||
if (pushStatus == model.StatusOnline || !ok) && (status.ActiveChannel != channelID || model.GetMillis()-status.LastActivityAt > model.StatusChannelTimeout) {
|
sendOnlineNotification := status.ActiveChannel != channelID || //We are in a different channel
|
||||||
|
model.GetMillis()-status.LastActivityAt > model.StatusChannelTimeout || //It has been a while since we were last active on this channel
|
||||||
|
isCRT //Is CRT, so being active in a channel doesn't mean you are seeing thread activity
|
||||||
|
|
||||||
|
if (pushStatus == model.StatusOnline || !ok) && sendOnlineNotification {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -441,12 +441,14 @@ func TestDoesStatusAllowPushNotification(t *testing.T) {
|
|||||||
away := &model.Status{UserId: userID, Status: model.StatusAway, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
away := &model.Status{UserId: userID, Status: model.StatusAway, Manual: false, LastActivityAt: 0, ActiveChannel: ""}
|
||||||
online := &model.Status{UserId: userID, Status: model.StatusOnline, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""}
|
online := &model.Status{UserId: userID, Status: model.StatusOnline, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: ""}
|
||||||
dnd := &model.Status{UserId: userID, Status: model.StatusDnd, Manual: true, LastActivityAt: model.GetMillis(), ActiveChannel: ""}
|
dnd := &model.Status{UserId: userID, Status: model.StatusDnd, Manual: true, LastActivityAt: model.GetMillis(), ActiveChannel: ""}
|
||||||
|
activeOnChannel := &model.Status{UserId: userID, Status: model.StatusOnline, Manual: false, LastActivityAt: model.GetMillis(), ActiveChannel: channelID}
|
||||||
|
|
||||||
tt := []struct {
|
tt := []struct {
|
||||||
name string
|
name string
|
||||||
userNotifySetting string
|
userNotifySetting string
|
||||||
status *model.Status
|
status *model.Status
|
||||||
channelID string
|
channelID string
|
||||||
|
isCRT bool
|
||||||
expected model.NotificationReason
|
expected model.NotificationReason
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -491,6 +493,21 @@ func TestDoesStatusAllowPushNotification(t *testing.T) {
|
|||||||
channelID: "",
|
channelID: "",
|
||||||
expected: model.NotificationReasonUserIsActive,
|
expected: model.NotificationReasonUserIsActive,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "WHEN props is ONLINE and user is online and active within the channel",
|
||||||
|
userNotifySetting: model.StatusOnline,
|
||||||
|
status: activeOnChannel,
|
||||||
|
channelID: channelID,
|
||||||
|
expected: model.NotificationReasonUserIsActive,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "WHEN props is ONLINE and user is online and active within a thread in the channel",
|
||||||
|
userNotifySetting: model.StatusOnline,
|
||||||
|
status: activeOnChannel,
|
||||||
|
channelID: channelID,
|
||||||
|
expected: "",
|
||||||
|
isCRT: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "WHEN props is ONLINE and user is dnd with channel",
|
name: "WHEN props is ONLINE and user is dnd with channel",
|
||||||
userNotifySetting: model.StatusOnline,
|
userNotifySetting: model.StatusOnline,
|
||||||
@@ -623,7 +640,7 @@ func TestDoesStatusAllowPushNotification(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
userNotifyProps := make(map[string]string)
|
userNotifyProps := make(map[string]string)
|
||||||
userNotifyProps["push_status"] = tc.userNotifySetting
|
userNotifyProps["push_status"] = tc.userNotifySetting
|
||||||
assert.Equal(t, tc.expected, DoesStatusAllowPushNotification(userNotifyProps, tc.status, tc.channelID))
|
assert.Equal(t, tc.expected, DoesStatusAllowPushNotification(userNotifyProps, tc.status, tc.channelID, tc.isCRT))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {ConnectedProps} from 'react-redux';
|
|||||||
|
|
||||||
import type {Channel} from '@mattermost/types/channels';
|
import type {Channel} from '@mattermost/types/channels';
|
||||||
|
|
||||||
import {favoriteChannel, unfavoriteChannel, markChannelAsRead} from 'mattermost-redux/actions/channels';
|
import {favoriteChannel, unfavoriteChannel, markMultipleChannelsAsRead} from 'mattermost-redux/actions/channels';
|
||||||
import Permissions from 'mattermost-redux/constants/permissions';
|
import Permissions from 'mattermost-redux/constants/permissions';
|
||||||
import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories';
|
import {getCategoryInTeamWithChannel} from 'mattermost-redux/selectors/entities/channel_categories';
|
||||||
import {isFavoriteChannel} from 'mattermost-redux/selectors/entities/channels';
|
import {isFavoriteChannel} from 'mattermost-redux/selectors/entities/channels';
|
||||||
@@ -66,7 +66,7 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
markChannelAsRead,
|
markMultipleChannelsAsRead,
|
||||||
markMostRecentPostInChannelAsUnread,
|
markMostRecentPostInChannelAsUnread,
|
||||||
favoriteChannel,
|
favoriteChannel,
|
||||||
unfavoriteChannel,
|
unfavoriteChannel,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ describe('components/sidebar/sidebar_channel/sidebar_channel_menu', () => {
|
|||||||
onToggleMenu: jest.fn(),
|
onToggleMenu: jest.fn(),
|
||||||
multiSelectedChannelIds: [],
|
multiSelectedChannelIds: [],
|
||||||
displayedChannels: [],
|
displayedChannels: [],
|
||||||
markChannelAsRead: jest.fn(),
|
markMultipleChannelsAsRead: jest.fn(),
|
||||||
markMostRecentPostInChannelAsUnread: jest.fn(),
|
markMostRecentPostInChannelAsUnread: jest.fn(),
|
||||||
favoriteChannel: jest.fn(),
|
favoriteChannel: jest.fn(),
|
||||||
unfavoriteChannel: jest.fn(),
|
unfavoriteChannel: jest.fn(),
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ const SidebarChannelMenu = (props: Props) => {
|
|||||||
let markAsReadUnreadMenuItem: JSX.Element | null = null;
|
let markAsReadUnreadMenuItem: JSX.Element | null = null;
|
||||||
if (props.isUnread) {
|
if (props.isUnread) {
|
||||||
function handleMarkAsRead() {
|
function handleMarkAsRead() {
|
||||||
props.markChannelAsRead(props.channel.id, true);
|
// We use mark multiple to not update the active channel in the server
|
||||||
|
props.markMultipleChannelsAsRead({[props.channel.id]: Date.now()});
|
||||||
trackEvent('ui', 'ui_sidebar_channel_menu_markAsRead');
|
trackEvent('ui', 'ui_sidebar_channel_menu_markAsRead');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {connect} from 'react-redux';
|
|||||||
import type {ConnectedProps} from 'react-redux';
|
import type {ConnectedProps} from 'react-redux';
|
||||||
import type {RouteComponentProps} from 'react-router-dom';
|
import type {RouteComponentProps} from 'react-router-dom';
|
||||||
|
|
||||||
import {fetchAllMyTeamsChannelsAndChannelMembersREST, fetchChannelsAndMembers} from 'mattermost-redux/actions/channels';
|
import {fetchAllMyTeamsChannelsAndChannelMembersREST, fetchChannelsAndMembers, unsetActiveChannelOnServer} from 'mattermost-redux/actions/channels';
|
||||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||||
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
|
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||||
import {getCurrentTeamId, getMyTeams} from 'mattermost-redux/selectors/entities/teams';
|
import {getCurrentTeamId, getMyTeams} from 'mattermost-redux/selectors/entities/teams';
|
||||||
@@ -55,6 +55,7 @@ const mapDispatchToProps = {
|
|||||||
markChannelAsReadOnFocus,
|
markChannelAsReadOnFocus,
|
||||||
initializeTeam,
|
initializeTeam,
|
||||||
joinTeam,
|
joinTeam,
|
||||||
|
unsetActiveChannelOnServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ function TeamController(props: Props) {
|
|||||||
function handleBlur() {
|
function handleBlur() {
|
||||||
window.isActive = false;
|
window.isActive = false;
|
||||||
blurTime.current = Date.now();
|
blurTime.current = Date.now();
|
||||||
|
props.unsetActiveChannelOnServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeydown(event: KeyboardEvent) {
|
function handleKeydown(event: KeyboardEvent) {
|
||||||
|
|||||||
@@ -701,6 +701,21 @@ export function updateApproximateViewTime(channelId: string): ActionFuncAsync {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function unsetActiveChannelOnServer(): ActionFuncAsync {
|
||||||
|
return async (dispatch, getState) => {
|
||||||
|
try {
|
||||||
|
// The view channel api in the server handles the active channel
|
||||||
|
await Client4.viewMyChannel('');
|
||||||
|
} catch (error) {
|
||||||
|
forceLogoutIfNecessary(error, dispatch, getState);
|
||||||
|
dispatch(logError(error));
|
||||||
|
return {data: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {data: true};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function readMultipleChannels(channelIds: string[]): ActionFuncAsync {
|
export function readMultipleChannels(channelIds: string[]): ActionFuncAsync {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
let response;
|
let response;
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user