Hotfix: PLT-4779 Fixing scrolling on loading a channel and missing DM channel headers (#4584)
* Added all parameters to call tracker ids when getting profiles * Changed channel header rendering to not depend on knowing all users in a DM channel * Added comment about a race condition in UserActions.populateDMChannelsWithProfiles * Added a fixed-height placeholder for the ChannelHeader when its state isn't valid for rendering
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
477dc6c4b6
Коммит
a9824a3653
@@ -135,6 +135,7 @@ function populateDMChannelsWithProfiles(userIds) {
|
|||||||
const currentUserId = UserStore.getCurrentId();
|
const currentUserId = UserStore.getCurrentId();
|
||||||
|
|
||||||
for (let i = 0; i < userIds.length; i++) {
|
for (let i = 0; i < userIds.length; i++) {
|
||||||
|
// TODO There's a race condition here for DM channels if those channels aren't loaded yet
|
||||||
const channelName = getDirectChannelName(currentUserId, userIds[i]);
|
const channelName = getDirectChannelName(currentUserId, userIds[i]);
|
||||||
const channel = ChannelStore.getByName(channelName);
|
const channel = ChannelStore.getByName(channelName);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
|
|||||||
@@ -68,12 +68,18 @@ export default class ChannelHeader extends React.Component {
|
|||||||
const stats = ChannelStore.getStats(this.props.channelId);
|
const stats = ChannelStore.getStats(this.props.channelId);
|
||||||
const users = UserStore.getProfileListInChannel(this.props.channelId);
|
const users = UserStore.getProfileListInChannel(this.props.channelId);
|
||||||
|
|
||||||
|
let otherUserId = null;
|
||||||
|
if (channel.type === 'D') {
|
||||||
|
otherUserId = Utils.getUserIdFromChannelName(channel);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel,
|
channel,
|
||||||
memberChannel: ChannelStore.getMyMember(this.props.channelId),
|
memberChannel: ChannelStore.getMyMember(this.props.channelId),
|
||||||
users,
|
users,
|
||||||
userCount: stats.member_count,
|
userCount: stats.member_count,
|
||||||
currentUser: UserStore.getCurrentUser(),
|
currentUser: UserStore.getCurrentUser(),
|
||||||
|
otherUserId,
|
||||||
enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true),
|
enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true),
|
||||||
isBusy: WebrtcStore.isBusy(),
|
isBusy: WebrtcStore.isBusy(),
|
||||||
isFavorite: channel && ChannelUtils.isFavoriteChannel(channel)
|
isFavorite: channel && ChannelUtils.isFavoriteChannel(channel)
|
||||||
@@ -84,7 +90,6 @@ export default class ChannelHeader extends React.Component {
|
|||||||
if (!this.state.channel ||
|
if (!this.state.channel ||
|
||||||
!this.state.memberChannel ||
|
!this.state.memberChannel ||
|
||||||
!this.state.users ||
|
!this.state.users ||
|
||||||
(Object.keys(this.state.users).length === 0 && this.state.channel.type === 'D') ||
|
|
||||||
!this.state.userCount ||
|
!this.state.userCount ||
|
||||||
!this.state.currentUser) {
|
!this.state.currentUser) {
|
||||||
return false;
|
return false;
|
||||||
@@ -240,7 +245,10 @@ export default class ChannelHeader extends React.Component {
|
|||||||
const flagIcon = Constants.FLAG_ICON_SVG;
|
const flagIcon = Constants.FLAG_ICON_SVG;
|
||||||
|
|
||||||
if (!this.validState()) {
|
if (!this.validState()) {
|
||||||
return null;
|
// Use an empty div to make sure the header's height stays constant
|
||||||
|
return (
|
||||||
|
<div className='channel-header'/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = this.state.channel;
|
const channel = this.state.channel;
|
||||||
@@ -285,7 +293,7 @@ export default class ChannelHeader extends React.Component {
|
|||||||
|
|
||||||
if (isDirect) {
|
if (isDirect) {
|
||||||
const userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
const userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
||||||
const contact = this.state.users[0];
|
const otherUserId = this.state.otherUserId;
|
||||||
|
|
||||||
const teammateId = Utils.getUserIdFromChannelName(channel);
|
const teammateId = Utils.getUserIdFromChannelName(channel);
|
||||||
channelTitle = Utils.displayUsername(teammateId);
|
channelTitle = Utils.displayUsername(teammateId);
|
||||||
@@ -293,7 +301,7 @@ export default class ChannelHeader extends React.Component {
|
|||||||
const webrtcEnabled = global.mm_config.EnableWebrtc === 'true' && userMedia && Utils.isFeatureEnabled(PreReleaseFeatures.WEBRTC_PREVIEW);
|
const webrtcEnabled = global.mm_config.EnableWebrtc === 'true' && userMedia && Utils.isFeatureEnabled(PreReleaseFeatures.WEBRTC_PREVIEW);
|
||||||
|
|
||||||
if (webrtcEnabled) {
|
if (webrtcEnabled) {
|
||||||
const isOffline = UserStore.getStatus(contact.id) === UserStatuses.OFFLINE;
|
const isOffline = UserStore.getStatus(otherUserId) === UserStatuses.OFFLINE;
|
||||||
const busy = this.state.isBusy;
|
const busy = this.state.isBusy;
|
||||||
let circleClass = '';
|
let circleClass = '';
|
||||||
let webrtcMessage;
|
let webrtcMessage;
|
||||||
@@ -321,7 +329,7 @@ export default class ChannelHeader extends React.Component {
|
|||||||
<div className='webrtc__header'>
|
<div className='webrtc__header'>
|
||||||
<a
|
<a
|
||||||
href='#'
|
href='#'
|
||||||
onClick={() => this.initWebrtc(contact.id, !isOffline)}
|
onClick={() => this.initWebrtc(otherUserId, !isOffline)}
|
||||||
disabled={isOffline}
|
disabled={isOffline}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@charset 'UTF-8';
|
@charset 'UTF-8';
|
||||||
|
|
||||||
.channel-header {
|
.channel-header {
|
||||||
@include flex(0 0 56px);
|
@include flex(0 0 57px);
|
||||||
border-left: none;
|
border-left: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 56px;
|
line-height: 56px;
|
||||||
|
|||||||
@@ -298,15 +298,17 @@ export function getChannelMember(channelId, userId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getUser(userId) {
|
export function getUser(userId) {
|
||||||
if (isCallInProgress(`getUser${userId}`)) {
|
const callName = `getUser${userId}`;
|
||||||
|
|
||||||
|
if (isCallInProgress(callName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker[`getUser${userId}`] = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getUser(
|
Client.getUser(
|
||||||
userId,
|
userId,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker[`getUser${userId}`] = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILE,
|
type: ActionTypes.RECEIVED_PROFILE,
|
||||||
@@ -314,23 +316,25 @@ export function getUser(userId) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker[`getUser${userId}`] = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getUser');
|
dispatchError(err, 'getUser');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfiles(offset = UserStore.getPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
export function getProfiles(offset = UserStore.getPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||||
if (isCallInProgress(`getProfiles${offset}${limit}`)) {
|
const callName = `getProfiles${offset}${limit}`;
|
||||||
|
|
||||||
|
if (isCallInProgress(callName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker[`getProfiles${offset}${limit}`] = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getProfiles(
|
Client.getProfiles(
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker[`getProfiles${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILES,
|
type: ActionTypes.RECEIVED_PROFILES,
|
||||||
@@ -338,24 +342,26 @@ export function getProfiles(offset = UserStore.getPagingOffset(), limit = Consta
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker[`getProfiles${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getProfiles');
|
dispatchError(err, 'getProfiles');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfilesInTeam(teamId = TeamStore.getCurrentId(), offset = UserStore.getInTeamPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
export function getProfilesInTeam(teamId = TeamStore.getCurrentId(), offset = UserStore.getInTeamPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||||
if (isCallInProgress(`getProfilesInTeam${offset}${limit}`)) {
|
const callName = `getProfilesInTeam${teamId}${offset}${limit}`;
|
||||||
|
|
||||||
|
if (isCallInProgress(callName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker[`getProfilesInTeam${offset}${limit}`] = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getProfilesInTeam(
|
Client.getProfilesInTeam(
|
||||||
teamId,
|
teamId,
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker[`getProfilesInTeam${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILES_IN_TEAM,
|
type: ActionTypes.RECEIVED_PROFILES_IN_TEAM,
|
||||||
@@ -366,24 +372,26 @@ export function getProfilesInTeam(teamId = TeamStore.getCurrentId(), offset = Us
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker[`getProfilesInTeam${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getProfilesInTeam');
|
dispatchError(err, 'getProfilesInTeam');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfilesInChannel(channelId = ChannelStore.getCurrentId(), offset = UserStore.getInChannelPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
export function getProfilesInChannel(channelId = ChannelStore.getCurrentId(), offset = UserStore.getInChannelPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||||
if (isCallInProgress(`getProfilesInChannel${offset}${limit}`)) {
|
const callName = `getProfilesInChannel${channelId}${offset}${limit}`;
|
||||||
|
|
||||||
|
if (isCallInProgress()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker[`getProfilesInChannel${offset}${limit}`] = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getProfilesInChannel(
|
Client.getProfilesInChannel(
|
||||||
channelId,
|
channelId,
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker[`getProfilesInChannel${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILES_IN_CHANNEL,
|
type: ActionTypes.RECEIVED_PROFILES_IN_CHANNEL,
|
||||||
@@ -396,24 +404,26 @@ export function getProfilesInChannel(channelId = ChannelStore.getCurrentId(), of
|
|||||||
loadStatusesForProfilesMap(data);
|
loadStatusesForProfilesMap(data);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker[`getProfilesInChannel${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getProfilesInChannel');
|
dispatchError(err, 'getProfilesInChannel');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfilesNotInChannel(channelId = ChannelStore.getCurrentId(), offset = UserStore.getNotInChannelPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
export function getProfilesNotInChannel(channelId = ChannelStore.getCurrentId(), offset = UserStore.getNotInChannelPagingOffset(), limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||||
if (isCallInProgress(`getProfilesNotInChannel${offset}${limit}`)) {
|
const callName = `getProfilesNotInChannel${channelId}${offset}${limit}`;
|
||||||
|
|
||||||
|
if (isCallInProgress(callName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker[`getProfilesNotInChannel${offset}${limit}`] = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getProfilesNotInChannel(
|
Client.getProfilesNotInChannel(
|
||||||
channelId,
|
channelId,
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker[`getProfilesNotInChannel${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL,
|
type: ActionTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL,
|
||||||
@@ -426,14 +436,16 @@ export function getProfilesNotInChannel(channelId = ChannelStore.getCurrentId(),
|
|||||||
loadStatusesForProfilesMap(data);
|
loadStatusesForProfilesMap(data);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker[`getProfilesNotInChannel${offset}${limit}`] = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getProfilesNotInChannel');
|
dispatchError(err, 'getProfilesNotInChannel');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProfilesByIds(userIds) {
|
export function getProfilesByIds(userIds) {
|
||||||
if (isCallInProgress('getProfilesByIds')) {
|
const callName = 'getProfilesByIds' + JSON.stringify(userIds);
|
||||||
|
|
||||||
|
if (isCallInProgress(callName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,11 +453,11 @@ export function getProfilesByIds(userIds) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callTracker.getProfilesByIds = utils.getTimestamp();
|
callTracker[callName] = utils.getTimestamp();
|
||||||
Client.getProfilesByIds(
|
Client.getProfilesByIds(
|
||||||
userIds,
|
userIds,
|
||||||
(data) => {
|
(data) => {
|
||||||
callTracker.getProfilesByIds = 0;
|
callTracker[callName] = 0;
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECEIVED_PROFILES,
|
type: ActionTypes.RECEIVED_PROFILES,
|
||||||
@@ -453,7 +465,7 @@ export function getProfilesByIds(userIds) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
callTracker.getProfilesByIds = 0;
|
callTracker[callName] = 0;
|
||||||
dispatchError(err, 'getProfilesByIds');
|
dispatchError(err, 'getProfilesByIds');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user