hunk.code_window: 		.post-create-footer {
   			padding-top: 10px;
   		}
   	}
   }
  
hunk.labels: keep keep add keep keep keep
hunk.after_edit: 		.post-right-comments-upload-in-progress {
   			padding: 6px 0;
   			color: #a8adb7;
   			margin-right: 10px;
   		}
  
hunk.file_path: web/sass-files/sass/partials/_post_right.scss
hunk.type: add
file: // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
  // See License.txt for license information.
  
  var client = require('./client.jsx');
  var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
  var ChannelStore = require('../stores/channel_store.jsx');
  var PostStore = require('../stores/post_store.jsx');
  var UserStore = require('../stores/user_store.jsx');
  var utils = require('./utils.jsx');
  
  var Constants = require('./constants.jsx');
  var ActionTypes = Constants.ActionTypes;
  
  // Used to track in progress async calls
  var callTracker = {};
  
  export function dispatchError(err, method) {
      AppDispatcher.handleServerAction({
          type: ActionTypes.RECIEVED_ERROR,
          err: err,
          method: method
      });
  }
  
  function isCallInProgress(callName) {
      if (!(callName in callTracker)) {
          return false;
      }
  
      if (callTracker[callName] === 0) {
          return false;
      }
  
      if (utils.getTimestamp() - callTracker[callName] > 5000) {
          //console.log('AsyncClient call ' + callName + ' expired after more than 5 seconds');
          return false;
      }
  
      return true;
  }
  
  export function getChannels(force, updateLastViewed, checkVersion) {
      var channels = ChannelStore.getAll();
  
      if (channels.length === 0 || force) {
          if (isCallInProgress('getChannels')) {
              return;
          }
  
          callTracker.getChannels = utils.getTimestamp();
  
          client.getChannels(
              function getChannelsSuccess(data, textStatus, xhr) {
                  callTracker.getChannels = 0;
  
                  if (checkVersion) {
                      var serverVersion = xhr.getResponseHeader('X-Version-ID');
  
                      if (!UserStore.getLastVersion()) {
                          UserStore.setLastVersion(serverVersion);
                      }
  
                      if (serverVersion !== UserStore.getLastVersion()) {
                          UserStore.setLastVersion(serverVersion);
                          window.location.href = window.location.href;
                          console.log('Detected version update refreshing the page'); //eslint-disable-line no-console
                      }
                  }
  
                  if (xhr.status === 304 || !data) {
                      return;
                  }
  
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECIEVED_CHANNELS,
                      channels: data.channels,
                      members: data.members
                  });
              },
              function getChannelsFailure(err) {
                  callTracker.getChannels = 0;
                  dispatchError(err, 'getChannels');
              }
          );
      } else {
          if (isCallInProgress('getChannelCounts')) {
              return;
          }
  
          callTracker.getChannelCounts = utils.getTimestamp();
  
          client.getChannelCounts(
              function getChannelCountsSuccess(data, textStatus, xhr) {
                  callTracker.getChannelCounts = 0;
  
                  if (xhr.status === 304 || !data) {
                      return;
                  }
  
                  var countMap = data.counts;
                  var updateAtMap = data.update_times;
  
                  for (var id in countMap) {
                      if ({}.hasOwnProperty.call(countMap, id)) {
                          var c = ChannelStore.get(id);
                          var count = countMap[id];
                          var updateAt = updateAtMap[id];
                          if (!c || c.total_msg_count !== count || updateAt > c.update_at) {
                              getChannel(id);
                          }
                      }
                  }
              },
              function getChannelCountsFailure(err) {
                  callTracker.getChannelCounts = 0;
                  dispatchError(err, 'getChannelCounts');
              }
          );
      }
  
      if (updateLastViewed && ChannelStore.getCurrentId() != null) {
          updateLastViewedAt();
      }
  }
  
  export function getChannel(id) {
      if (isCallInProgress('getChannel' + id)) {
          return;
      }
  
      callTracker['getChannel' + id] = utils.getTimestamp();
  
      client.getChannel(id,
          function getChannelSuccess(data, textStatus, xhr) {
              callTracker['getChannel' + id] = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_CHANNEL,
                  channel: data.channel,
                  member: data.member
              });
          },
          function getChannelFailure(err) {
              callTracker['getChannel' + id] = 0;
              dispatchError(err, 'getChannel');
          }
      );
  }
  
  export function updateLastViewedAt() {
      const channelId = ChannelStore.getCurrentId();
  
      if (channelId === null) {
          return;
      }
  
      if (isCallInProgress(`updateLastViewed${channelId}`)) {
          return;
      }
  
      callTracker[`updateLastViewed${channelId}`] = utils.getTimestamp();
      client.updateLastViewedAt(
          channelId,
          () => {
              callTracker.updateLastViewed = 0;
          },
          (err) => {
              callTracker.updateLastViewed = 0;
              dispatchError(err, 'updateLastViewedAt');
          }
      );
  }
  
  export function getMoreChannels(force) {
      if (isCallInProgress('getMoreChannels')) {
          return;
      }
  
      if (ChannelStore.getMoreAll().loading || force) {
          callTracker.getMoreChannels = utils.getTimestamp();
          client.getMoreChannels(
              function getMoreChannelsSuccess(data, textStatus, xhr) {
                  callTracker.getMoreChannels = 0;
  
                  if (xhr.status === 304 || !data) {
                      return;
                  }
  
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECIEVED_MORE_CHANNELS,
                      channels: data.channels,
                      members: data.members
                  });
              },
              function getMoreChannelsFailure(err) {
                  callTracker.getMoreChannels = 0;
                  dispatchError(err, 'getMoreChannels');
              }
          );
      }
  }
  
  export function getChannelExtraInfo(force) {
      var channelId = ChannelStore.getCurrentId();
  
      if (channelId != null) {
          if (isCallInProgress('getChannelExtraInfo_' + channelId)) {
              return;
          }
          var minMembers = 0;
          if (ChannelStore.getCurrent() && ChannelStore.getCurrent().type === 'D') {
              minMembers = 1;
          }
  
          if (ChannelStore.getCurrentExtraInfo().members.length <= minMembers || force) {
              callTracker['getChannelExtraInfo_' + channelId] = utils.getTimestamp();
              client.getChannelExtraInfo(
                  channelId,
                  function getChannelExtraInfoSuccess(data, textStatus, xhr) {
                      callTracker['getChannelExtraInfo_' + channelId] = 0;
  
                      if (xhr.status === 304 || !data) {
                          return;
                      }
  
                      AppDispatcher.handleServerAction({
                          type: ActionTypes.RECIEVED_CHANNEL_EXTRA_INFO,
                          extra_info: data
                      });
                  },
                  function getChannelExtraInfoFailure(err) {
                      callTracker['getChannelExtraInfo_' + channelId] = 0;
                      dispatchError(err, 'getChannelExtraInfo');
                  }
              );
          }
      }
  }
  
  export function getProfiles() {
      if (isCallInProgress('getProfiles')) {
          return;
      }
  
      callTracker.getProfiles = utils.getTimestamp();
      client.getProfiles(
          function getProfilesSuccess(data, textStatus, xhr) {
              callTracker.getProfiles = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_PROFILES,
                  profiles: data
              });
          },
          function getProfilesFailure(err) {
              callTracker.getProfiles = 0;
              dispatchError(err, 'getProfiles');
          }
      );
  }
  
  export function getSessions() {
      if (isCallInProgress('getSessions')) {
          return;
      }
  
      callTracker.getSessions = utils.getTimestamp();
      client.getSessions(
          UserStore.getCurrentId(),
          function getSessionsSuccess(data, textStatus, xhr) {
              callTracker.getSessions = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_SESSIONS,
                  sessions: data
              });
          },
          function getSessionsFailure(err) {
              callTracker.getSessions = 0;
              dispatchError(err, 'getSessions');
          }
      );
  }
  
  export function getAudits() {
      if (isCallInProgress('getAudits')) {
          return;
      }
  
      callTracker.getAudits = utils.getTimestamp();
      client.getAudits(
          UserStore.getCurrentId(),
          function getAuditsSuccess(data, textStatus, xhr) {
              callTracker.getAudits = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_AUDITS,
                  audits: data
              });
          },
          function getAuditsFailure(err) {
              callTracker.getAudits = 0;
              dispatchError(err, 'getAudits');
          }
      );
  }
  
  export function getLogs() {
      if (isCallInProgress('getLogs')) {
          return;
      }
  
      callTracker.getLogs = utils.getTimestamp();
      client.getLogs(
          (data, textStatus, xhr) => {
              callTracker.getLogs = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_LOGS,
                  logs: data
              });
          },
          (err) => {
              callTracker.getLogs = 0;
              dispatchError(err, 'getLogs');
          }
      );
  }
  
  export function getConfig() {
      if (isCallInProgress('getConfig')) {
          return;
      }
  
      callTracker.getConfig = utils.getTimestamp();
      client.getConfig(
          (data, textStatus, xhr) => {
              callTracker.getConfig = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_CONFIG,
                  config: data
              });
          },
          (err) => {
              callTracker.getConfig = 0;
              dispatchError(err, 'getConfig');
          }
      );
  }
  
  export function getAllTeams() {
      if (isCallInProgress('getAllTeams')) {
          return;
      }
  
      callTracker.getAllTeams = utils.getTimestamp();
      client.getAllTeams(
          (data, textStatus, xhr) => {
              callTracker.getAllTeams = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_ALL_TEAMS,
                  teams: data
              });
          },
          (err) => {
              callTracker.getAllTeams = 0;
              dispatchError(err, 'getAllTeams');
          }
      );
  }
  
  export function findTeams(email) {
      if (isCallInProgress('findTeams_' + email)) {
          return;
      }
  
      var user = UserStore.getCurrentUser();
      if (user) {
          callTracker['findTeams_' + email] = utils.getTimestamp();
          client.findTeams(
              user.email,
              function findTeamsSuccess(data, textStatus, xhr) {
                  callTracker['findTeams_' + email] = 0;
  
                  if (xhr.status === 304 || !data) {
                      return;
                  }
  
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECIEVED_TEAMS,
                      teams: data
                  });
              },
              function findTeamsFailure(err) {
                  callTracker['findTeams_' + email] = 0;
                  dispatchError(err, 'findTeams');
              }
          );
      }
  }
  
  export function search(terms) {
      if (isCallInProgress('search_' + String(terms))) {
          return;
      }
  
      callTracker['search_' + String(terms)] = utils.getTimestamp();
      client.search(
          terms,
          function searchSuccess(data, textStatus, xhr) {
              callTracker['search_' + String(terms)] = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_SEARCH,
                  results: data
              });
          },
          function searchFailure(err) {
              callTracker['search_' + String(terms)] = 0;
              dispatchError(err, 'search');
          }
      );
  }
  
  export function getPostsPage(force, id, maxPosts) {
      if (PostStore.getCurrentPosts() == null || force) {
          var channelId = id;
          if (channelId == null) {
              channelId = ChannelStore.getCurrentId();
          }
  
          if (isCallInProgress('getPostsPage_' + channelId)) {
              return;
          }
  
          var postList = PostStore.getCurrentPosts();
  
          var max = maxPosts;
          if (max == null) {
              max = Constants.POST_CHUNK_SIZE * Constants.MAX_POST_CHUNKS;
          }
  
          // if we already have more than POST_CHUNK_SIZE posts,
          //   let's get the amount we have but rounded up to next multiple of POST_CHUNK_SIZE,
          //   with a max at maxPosts
          var numPosts = Math.min(max, Constants.POST_CHUNK_SIZE);
          if (postList && postList.order.length > 0) {
              numPosts = Math.min(max, Constants.POST_CHUNK_SIZE * Math.ceil(postList.order.length / Constants.POST_CHUNK_SIZE));
          }
  
          if (channelId != null) {
              callTracker['getPostsPage_' + channelId] = utils.getTimestamp();
  
              client.getPostsPage(
                  channelId,
                  0,
                  numPosts,
                  function getPostsPageSuccess(data, textStatus, xhr) {
                      if (xhr.status === 304 || !data) {
                          return;
                      }
  
                      AppDispatcher.handleServerAction({
                          type: ActionTypes.RECIEVED_POSTS,
                          id: channelId,
                          post_list: data
                      });
  
                      getProfiles();
                  },
                  function getPostsPageFailure(err) {
                      dispatchError(err, 'getPostsPage');
                  },
                  function getPostsPageComplete() {
                      callTracker['getPostsPage_' + channelId] = 0;
                  }
              );
          }
      }
  }
  
  export function getPosts(id) {
      var channelId = id;
      if (channelId == null) {
          if (ChannelStore.getCurrentId() == null) {
              return;
          }
          channelId = ChannelStore.getCurrentId();
      }
  
      if (isCallInProgress('getPosts_' + channelId)) {
          return;
      }
  
      if (PostStore.getCurrentPosts() == null) {
          getPostsPage(true, id, Constants.POST_CHUNK_SIZE);
          return;
      }
  
      var latestUpdate = PostStore.getLatestUpdate(channelId);
  
      callTracker['getPosts_' + channelId] = utils.getTimestamp();
  
      client.getPosts(
          channelId,
          latestUpdate,
          function success(data, textStatus, xhr) {
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_POSTS,
                  id: channelId,
                  post_list: data
              });
  
              getProfiles();
          },
          function fail(err) {
              dispatchError(err, 'getPosts');
          },
          function complete() {
              callTracker['getPosts_' + channelId] = 0;
          }
      );
  }
  
  export function getMe() {
      if (isCallInProgress('getMe')) {
          return;
      }
  
      callTracker.getMe = utils.getTimestamp();
      client.getMeSynchronous(
          function getMeSyncSuccess(data, textStatus, xhr) {
              callTracker.getMe = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_ME,
                  me: data
              });
          },
          function getMeSyncFailure(err) {
              callTracker.getMe = 0;
              dispatchError(err, 'getMe');
          }
      );
  }
  
  export function getStatuses() {
      if (isCallInProgress('getStatuses')) {
          return;
      }
  
      callTracker.getStatuses = utils.getTimestamp();
      client.getStatuses(
          function getStatusesSuccess(data, textStatus, xhr) {
              callTracker.getStatuses = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_STATUSES,
                  statuses: data
              });
          },
          function getStatusesFailure(err) {
              callTracker.getStatuses = 0;
              dispatchError(err, 'getStatuses');
          }
      );
  }
  
  export function getMyTeam() {
      if (isCallInProgress('getMyTeam')) {
          return;
      }
  
      callTracker.getMyTeam = utils.getTimestamp();
      client.getMyTeam(
          function getMyTeamSuccess(data, textStatus, xhr) {
              callTracker.getMyTeam = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_TEAM,
                  team: data
              });
          },
          function getMyTeamFailure(err) {
              callTracker.getMyTeam = 0;
              dispatchError(err, 'getMyTeam');
          }
      );
  }
  
  export function getDirectChannelPreferences() {
      if (isCallInProgress('getDirectChannelPreferences')) {
          return;
      }
  
      callTracker.getDirectChannelPreferences = utils.getTimestamp();
      client.getPreferenceCategory(
          Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW,
          (data, textStatus, xhr) => {
              callTracker.getDirectChannelPreferences = 0;
  
              if (xhr.status === 304 || !data) {
                  return;
              }
  
              AppDispatcher.handleServerAction({
                  type: ActionTypes.RECIEVED_PREFERENCES,
                  preferences: data
              });
          },
          (err) => {
              callTracker.getDirectChannelPreferences = 0;
              dispatchError(err, 'getDirectChannelPreferences');
          }
      );
  }
  
  export function savePreferences(preferences, success, error) {
      client.savePreferences(
          preferences,
          (data, textStatus, xhr) => {
              if (xhr.status !== 304) {
                  AppDispatcher.handleServerAction({
                      type: ActionTypes.RECIEVED_PREFERENCES,
                      preferences
                  });
              }
  
              if (success) {
                  success(data);
              }
          },
          (err) => {
              dispatchError(err, 'savePreferences');
  
              if (error) {
                  error();
              }
          }
      );
  }
  