hunk.code_window:         if (nextProps.useMilitaryTime !== this.props.useMilitaryTime) {
               return true;
           }
           if (!Utils.areObjectsEqual(nextState.flaggedPosts, this.state.flaggedPosts)) {
               return true;
           }
  
hunk.labels: keep keep keep keep add keep keep keep keep
hunk.after_edit:         if (nextState.previewsCollapsed !== this.state.previewsCollapsed) {
               return true;
           }
  
hunk.file_path: webapp/components/rhs_thread.jsx
hunk.type: add
file: // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
  // See License.txt for license information.
  
  import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
  
  import PreferenceStore from 'stores/preference_store.jsx';
  import TeamStore from 'stores/team_store.jsx';
  import UserStore from 'stores/user_store.jsx';
  import ChannelStore from 'stores/channel_store.jsx';
  
  import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx';
  
  import {getDirectChannelName} from 'utils/utils.jsx';
  import * as AsyncClient from 'utils/async_client.jsx';
  import Client from 'client/web_client.jsx';
  
  import {ActionTypes, Preferences} from 'utils/constants.jsx';
  
  export function switchFromLdapToEmail(email, password, ldapPassword, onSuccess, onError) {
      Client.ldapToEmail(
          email,
          password,
          ldapPassword,
          (data) => {
              if (data.follow_link) {
                  window.location.href = data.follow_link;
              }
  
              if (onSuccess) {
                  onSuccess(data);
              }
          },
          onError
      );
  }
  
  export function loadProfilesAndTeamMembers(offset, limit, teamId = TeamStore.getCurrentId(), success, error) {
      Client.getProfilesInTeam(
          teamId,
          offset,
          limit,
          (data) => {
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECEIVED_PROFILES_IN_TEAM,
                  profiles: data,
                  team_id: teamId,
                  offset,
                  count: Object.keys(data).length
              });
  
              loadTeamMembersForProfilesMap(data, teamId, success, error);
              loadStatusesForProfilesMap(data);
          },
          (err) => {
              AsyncClient.dispatchError(err, 'getProfilesInTeam');
          }
      );
  }
  
  export function loadTeamMembersForProfilesMap(profiles, teamId = TeamStore.getCurrentId(), success, error) {
      const membersToLoad = {};
      for (const pid in profiles) {
          if (!profiles.hasOwnProperty(pid)) {
              continue;
          }
  
          if (!TeamStore.hasActiveMemberInTeam(teamId, pid)) {
              membersToLoad[pid] = true;
          }
      }
  
      const list = Object.keys(membersToLoad);
      if (list.length === 0) {
          if (success) {
              success({});
          }
          return;
      }
  
      loadTeamMembersForProfiles(list, teamId, success, error);
  }
  
  export function loadTeamMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), success, error) {
      const membersToLoad = {};
      for (let i = 0; i < profiles.length; i++) {
          const pid = profiles[i].id;
  
          if (!TeamStore.hasActiveMemberInTeam(teamId, pid)) {
              membersToLoad[pid] = true;
          }
      }
  
      const list = Object.keys(membersToLoad);
      if (list.length === 0) {
          if (success) {
              success({});
          }
          return;
      }
  
      loadTeamMembersForProfiles(list, teamId, success, error);
  }
  
  function loadTeamMembersForProfiles(userIds, teamId, success, error) {
      Client.getTeamMembersByIds(
          teamId,
          userIds,
          (data) => {
              const memberMap = {};
              for (let i = 0; i < data.length; i++) {
                  memberMap[data[i].user_id] = data[i];
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECEIVED_MEMBERS_IN_TEAM,
                  team_id: teamId,
                  team_members: memberMap
              });
  
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'getTeamMembersByIds');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  function populateDMChannelsWithProfiles(userIds) {
      const currentUserId = UserStore.getCurrentId();
  
      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 channel = ChannelStore.getByName(channelName);
          if (channel) {
              UserStore.saveUserIdInChannel(channel.id, userIds[i]);
          }
      }
  }
  
  export function loadProfilesAndTeamMembersForDMSidebar() {
      const dmPrefs = PreferenceStore.getCategory(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
      const teamId = TeamStore.getCurrentId();
      const profilesToLoad = [];
      const membersToLoad = [];
  
      for (const [key, value] of dmPrefs) {
          if (value === 'true') {
              if (!UserStore.hasProfile(key)) {
                  profilesToLoad.push(key);
              }
              membersToLoad.push(key);
          }
      }
  
      if (profilesToLoad.length > 0) {
          Client.getProfilesByIds(
              profilesToLoad,
              (data) => {
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECEIVED_PROFILES,
                      profiles: data
                  });
  
                  // Use membersToLoad so we get all the DM profiles even if they were already loaded
                  populateDMChannelsWithProfiles(membersToLoad);
              },
              (err) => {
                  AsyncClient.dispatchError(err, 'getProfilesByIds');
              }
          );
      } else {
          populateDMChannelsWithProfiles(membersToLoad);
      }
  
      if (membersToLoad.length > 0) {
          Client.getTeamMembersByIds(
              teamId,
              membersToLoad,
              (data) => {
                  const memberMap = {};
                  for (let i = 0; i < data.length; i++) {
                      memberMap[data[i].user_id] = data[i];
                  }
  
                  const nonMembersMap = {};
                  for (let i = 0; i < membersToLoad.length; i++) {
                      if (!memberMap[membersToLoad[i]]) {
                          nonMembersMap[membersToLoad[i]] = true;
                      }
                  }
  
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECEIVED_MEMBERS_IN_TEAM,
                      team_id: teamId,
                      team_members: memberMap,
                      non_team_members: nonMembersMap
                  });
              },
              (err) => {
                  AsyncClient.dispatchError(err, 'getTeamMembersByIds');
              }
          );
      }
  }
  
  export function saveTheme(teamId, theme, onSuccess, onError) {
      AsyncClient.savePreference(
          Preferences.CATEGORY_THEME,
          teamId,
          JSON.stringify(theme),
          () => {
              onThemeSaved(teamId, theme, onSuccess);
          },
          (err) => {
              onError(err);
          }
      );
  }
  
  function onThemeSaved(teamId, theme, onSuccess) {
      const themePreferences = PreferenceStore.getCategory(Preferences.CATEGORY_THEME);
  
      if (teamId !== '' && themePreferences.size > 1) {
          // no extra handling to be done to delete team-specific themes
          onSuccess();
          return;
      }
  
      const toDelete = [];
  
      for (const [name] of themePreferences) {
          if (name === '' || name === teamId) {
              continue;
          }
  
          toDelete.push({
              user_id: UserStore.getCurrentId(),
              category: Preferences.CATEGORY_THEME,
              name
          });
      }
  
      if (toDelete.length > 0) {
          // we're saving a new global theme so delete any team-specific ones
          AsyncClient.deletePreferences(toDelete);
  
          // delete them locally before we hear from the server so that the UI flow is smoother
          AppDispatcher.handleServerAction({
              type: ActionTypes.DELETED_PREFERENCES,
              preferences: toDelete
          });
      }
  
      onSuccess();
  }
  
  export function searchUsers(term, teamId = TeamStore.getCurrentId(), options = {}, success, error) {
      Client.searchUsers(
          term,
          teamId,
          options,
          (data) => {
              loadStatusesForProfilesList(data);
  
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'searchUsers');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function autocompleteUsersInChannel(username, channelId, success, error) {
      Client.autocompleteUsersInChannel(
          username,
          channelId,
          (data) => {
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'autocompleteUsersInChannel');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function autocompleteUsersInTeam(username, success, error) {
      Client.autocompleteUsersInTeam(
          username,
          (data) => {
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'autocompleteUsersInTeam');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function autocompleteUsers(username, success, error) {
      Client.autocompleteUsers(
          username,
          (data) => {
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'autocompleteUsers');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function updateUser(username, success, error) {
      Client.updateUser(
          username,
          (data) => {
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'updateUser');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function generateMfaSecret(success, error) {
      Client.generateMfaSecret(
          (data) => {
              if (success) {
                  success(data);
              }
          },
          (err) => {
              AsyncClient.dispatchError(err, 'generateMfaSecret');
  
              if (error) {
                  error(err);
              }
          }
      );
  }
  
  export function updateUserRoles(userId, newRoles, success, error) {
      Client.updateUserRoles(
        userId,
        newRoles,
        () => {
            AsyncClient.getUser(this.props.user.id);
  
            if (success) {
                success();
            }
        },
        (err) => {
            if (error) {
                error(err);
            }
        }
      );
  }
  