You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			150 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			TypeScript
		
	
import { createSelector } from 'reselect';
 | 
						|
import { format } from '../../types/PhoneNumber';
 | 
						|
 | 
						|
import { LocalizerType } from '../../types/Util';
 | 
						|
import { StateType } from '../reducer';
 | 
						|
import {
 | 
						|
  ConversationLookupType,
 | 
						|
  ConversationsStateType,
 | 
						|
  ConversationType,
 | 
						|
} from '../ducks/conversations';
 | 
						|
 | 
						|
import { getIntl, getRegionCode, getUserNumber } from './user';
 | 
						|
 | 
						|
export const getConversations = (state: StateType): ConversationsStateType =>
 | 
						|
  state.conversations;
 | 
						|
 | 
						|
export const getConversationLookup = createSelector(
 | 
						|
  getConversations,
 | 
						|
  (state: ConversationsStateType): ConversationLookupType => {
 | 
						|
    return state.conversationLookup;
 | 
						|
  }
 | 
						|
);
 | 
						|
 | 
						|
export const getSelectedConversation = createSelector(
 | 
						|
  getConversations,
 | 
						|
  (state: ConversationsStateType): string | undefined => {
 | 
						|
    return state.selectedConversation;
 | 
						|
  }
 | 
						|
);
 | 
						|
 | 
						|
export const getShowArchived = createSelector(
 | 
						|
  getConversations,
 | 
						|
  (state: ConversationsStateType): boolean => {
 | 
						|
    return Boolean(state.showArchived);
 | 
						|
  }
 | 
						|
);
 | 
						|
 | 
						|
function getConversationTitle(
 | 
						|
  conversation: ConversationType,
 | 
						|
  options: { i18n: LocalizerType; ourRegionCode: string }
 | 
						|
): string {
 | 
						|
  if (conversation.name) {
 | 
						|
    return conversation.name;
 | 
						|
  }
 | 
						|
 | 
						|
  if (conversation.type === 'group') {
 | 
						|
    const { i18n } = options;
 | 
						|
 | 
						|
    return i18n('unknownGroup');
 | 
						|
  }
 | 
						|
 | 
						|
  return format(conversation.phoneNumber, options);
 | 
						|
}
 | 
						|
 | 
						|
const collator = new Intl.Collator();
 | 
						|
 | 
						|
export const _getConversationComparator = (
 | 
						|
  i18n: LocalizerType,
 | 
						|
  ourRegionCode: string
 | 
						|
) => {
 | 
						|
  return (left: ConversationType, right: ConversationType): number => {
 | 
						|
    const leftTimestamp = left.timestamp;
 | 
						|
    const rightTimestamp = right.timestamp;
 | 
						|
    if (leftTimestamp && !rightTimestamp) {
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    if (rightTimestamp && !leftTimestamp) {
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
    if (leftTimestamp && rightTimestamp && leftTimestamp !== rightTimestamp) {
 | 
						|
      return rightTimestamp - leftTimestamp;
 | 
						|
    }
 | 
						|
 | 
						|
    const leftTitle = getConversationTitle(left, {
 | 
						|
      i18n,
 | 
						|
      ourRegionCode,
 | 
						|
    }).toLowerCase();
 | 
						|
    const rightTitle = getConversationTitle(right, {
 | 
						|
      i18n,
 | 
						|
      ourRegionCode,
 | 
						|
    }).toLowerCase();
 | 
						|
 | 
						|
    return collator.compare(leftTitle, rightTitle);
 | 
						|
  };
 | 
						|
};
 | 
						|
export const getConversationComparator = createSelector(
 | 
						|
  getIntl,
 | 
						|
  getRegionCode,
 | 
						|
  _getConversationComparator
 | 
						|
);
 | 
						|
 | 
						|
export const _getLeftPaneLists = (
 | 
						|
  lookup: ConversationLookupType,
 | 
						|
  comparator: (left: ConversationType, right: ConversationType) => number,
 | 
						|
  selectedConversation?: string
 | 
						|
): {
 | 
						|
  conversations: Array<ConversationType>;
 | 
						|
  archivedConversations: Array<ConversationType>;
 | 
						|
  friends: Array<ConversationType>;
 | 
						|
} => {
 | 
						|
  const values = Object.values(lookup);
 | 
						|
  const sorted = values.sort(comparator);
 | 
						|
 | 
						|
  const conversations: Array<ConversationType> = [];
 | 
						|
  const archivedConversations: Array<ConversationType> = [];
 | 
						|
  const friends: Array<ConversationType> = [];
 | 
						|
 | 
						|
  const max = sorted.length;
 | 
						|
  for (let i = 0; i < max; i += 1) {
 | 
						|
    let conversation = sorted[i];
 | 
						|
 | 
						|
    if (selectedConversation === conversation.id) {
 | 
						|
      conversation = {
 | 
						|
        ...conversation,
 | 
						|
        isSelected: true,
 | 
						|
      };
 | 
						|
    }
 | 
						|
 | 
						|
    if (conversation.isFriend) {
 | 
						|
      friends.push(conversation);
 | 
						|
    }
 | 
						|
 | 
						|
    if (!conversation.activeAt) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (conversation.isArchived) {
 | 
						|
      archivedConversations.push(conversation);
 | 
						|
    } else {
 | 
						|
      conversations.push(conversation);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return { conversations, archivedConversations, friends };
 | 
						|
};
 | 
						|
 | 
						|
export const getLeftPaneLists = createSelector(
 | 
						|
  getConversationLookup,
 | 
						|
  getConversationComparator,
 | 
						|
  getSelectedConversation,
 | 
						|
  _getLeftPaneLists
 | 
						|
);
 | 
						|
 | 
						|
export const getMe = createSelector(
 | 
						|
  [getConversationLookup, getUserNumber],
 | 
						|
  (lookup: ConversationLookupType, ourNumber: string): ConversationType => {
 | 
						|
    return lookup[ourNumber];
 | 
						|
  }
 | 
						|
);
 |