<commit_before>// @flow

import type { BaseAppState } from '../types/redux-types';
import type {
  UserInfo,
  RelativeUserInfo,
  AccountUserInfo,
} from '../types/user-types';
import type {
  RawThreadInfo,
  MemberInfo,
  RelativeMemberInfo,
} from '../types/thread-types';

import { createSelector } from 'reselect';
import _memoize from 'lodash/memoize';
import _keys from 'lodash/keys';

import SearchIndex from '../shared/search-index';
import { threadActualMembers } from '../shared/thread-utils';

// Used for specific message payloads that include an array of user IDs, ie.
// array of initial users, array of added users
function userIDsToRelativeUserInfos(
  userIDs: string[],
  viewerID: ?string,
  userInfos: { [id: string]: UserInfo },
): RelativeUserInfo[] {
  const relativeUserInfos = [];
  for (let userID of userIDs) {
    const username = userInfos[userID] ? userInfos[userID].username : null;
    if (userID === viewerID) {
      relativeUserInfos.unshift({
        id: userID,
        username,
        isViewer: true,
      });
    } else {
      relativeUserInfos.push({
        id: userID,
        username,
        isViewer: false,
      });
    }
  }
  return relativeUserInfos;
}

// Includes current user at the start
const baseRelativeMemberInfoSelectorForMembersOfThread = (threadID: string) =>
  createSelector(
    (state: BaseAppState<*>) => state.threadStore.threadInfos[threadID],
    (state: BaseAppState<*>) =>
      state.currentUserInfo && state.currentUserInfo.id,
    (state: BaseAppState<*>) => state.userInfos,
    (
      threadInfo: ?RawThreadInfo,
      currentUserID: ?string,
      userInfos: { [id: string]: UserInfo },
    ): RelativeMemberInfo[] => {
      const relativeMemberInfos = [];
      if (!threadInfo) {
        return relativeMemberInfos;
      }
      const memberInfos = threadInfo.members;
      for (let memberInfo of memberInfos) {
        const username = userInfos[memberInfo.id]
          ? userInfos[memberInfo.id].username
          : null;
        if (memberInfo.id === currentUserID) {
          relativeMemberInfos.unshift({
            id: memberInfo.id,
            role: memberInfo.role,
            permissions: memberInfo.permissions,
            username,
            isViewer: true,
          });
        } else {
          relativeMemberInfos.push({
            id: memberInfo.id,
            role: memberInfo.role,
            permissions: memberInfo.permissions,
            username,
            isViewer: false,
          });
        }
      }
      return relativeMemberInfos;
    },
  );

const relativeMemberInfoSelectorForMembersOfThread: (
  threadID: string,
) => (state: BaseAppState<*>) => RelativeMemberInfo[] = _memoize(
  baseRelativeMemberInfoSelectorForMembersOfThread,
);

// If threadID is null, then all users except the logged-in user are returned
const baseUserInfoSelectorForOtherMembersOfThread = (threadID: ?string) =>
  createSelector(<commit_msg>[lib] Don't list current user as a member if they're not<commit_after>// @flow

import type { BaseAppState } from '../types/redux-types';
import type {
  UserInfo,
  RelativeUserInfo,
  AccountUserInfo,
} from '../types/user-types';
import {
  type RawThreadInfo,
  type MemberInfo,
  type RelativeMemberInfo,
  threadPermissions,
} from '../types/thread-types';

import { createSelector } from 'reselect';
import _memoize from 'lodash/memoize';
import _keys from 'lodash/keys';

import SearchIndex from '../shared/search-index';
import { threadActualMembers } from '../shared/thread-utils';

// Used for specific message payloads that include an array of user IDs, ie.
// array of initial users, array of added users
function userIDsToRelativeUserInfos(
  userIDs: string[],
  viewerID: ?string,
  userInfos: { [id: string]: UserInfo },
): RelativeUserInfo[] {
  const relativeUserInfos = [];
  for (let userID of userIDs) {
    const username = userInfos[userID] ? userInfos[userID].username : null;
    if (userID === viewerID) {
      relativeUserInfos.unshift({
        id: userID,
        username,
        isViewer: true,
      });
    } else {
      relativeUserInfos.push({
        id: userID,
        username,
        isViewer: false,
      });
    }
  }
  return relativeUserInfos;
}

// Includes current user at the start
const baseRelativeMemberInfoSelectorForMembersOfThread = (threadID: string) =>
  createSelector(
    (state: BaseAppState<*>) => state.threadStore.threadInfos[threadID],
    (state: BaseAppState<*>) =>
      state.currentUserInfo && state.currentUserInfo.id,
    (state: BaseAppState<*>) => state.userInfos,
    (
      threadInfo: ?RawThreadInfo,
      currentUserID: ?string,
      userInfos: { [id: string]: UserInfo },
    ): RelativeMemberInfo[] => {
      const relativeMemberInfos = [];
      if (!threadInfo) {
        return relativeMemberInfos;
      }
      const memberInfos = threadInfo.members;
      for (let memberInfo of memberInfos) {
        const username = userInfos[memberInfo.id]
          ? userInfos[memberInfo.id].username
          : null;
        const canChangeRoles =
          memberInfo.permissions[threadPermissions.CHANGE_ROLE] &&
          memberInfo.permissions[threadPermissions.CHANGE_ROLE].value;
        if (
          memberInfo.id === currentUserID &&
          (memberInfo.role || canChangeRoles)
        ) {
          relativeMemberInfos.unshift({
            id: memberInfo.id,
            role: memberInfo.role,
            permissions: memberInfo.permissions,
            username,
            isViewer: true,
          });
        } else if (memberInfo.id !== currentUserID) {
          relativeMemberInfos.push({
            id: memberInfo.id,
            role: memberInfo.role,
            permissions: memberInfo.permissions,
            username,
            isViewer: false,
          });
        }
      }
      return relativeMemberInfos;
    },
  );

const relativeMemberInfoSelectorForMembersOfThread: (
  threadID: string,
) => (state: BaseAppState<*>) => RelativeMemberInfo[] = _memoize(
  baseRelativeMemberInfoSelectorForMembersOfThread,
);

// If threadID is null, then all users except the logged-in user are returned
const baseUserInfoSelectorForOtherMembersOfThread = (threadID: ?string) =>
  createSelector(
{'fraction_non_alphanumeric': 0.11089835647040051, 'fraction_numerical': 0.0, 'mean_word_length': 2.79648697758934, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1662293', 'n_tokens_mistral': 1828, 'n_tokens_neox': 1816, 'n_words': 431}