<commit_before>import { ADDRESS_STATUS } from 'proton-shared/lib/constants';
import { unique } from 'proton-shared/lib/helpers/array';
import { addPlusAlias, removeEmailAlias } from 'proton-shared/lib/helpers/email';
import { Address, Key } from 'proton-shared/lib/interfaces';
import { Recipient } from 'proton-shared/lib/interfaces/Address';
import { ContactEmail, ContactGroup } from 'proton-shared/lib/interfaces/contacts';
import { c } from 'ttag';
import { RecipientGroup, RecipientOrGroup } from '../models/address';
import { Conversation } from '../models/conversation';
import { Element } from '../models/element';
import { Message } from '../models/message';
import { getContactOfRecipient, getContactsOfGroup } from './contacts';
import { isMessage } from './elements';

export const REGEX_RECIPIENT = /(.*?)\s*<([^>]*)>/;

/**
 * Get address from email
 * Remove + alias and transform to lower case
 */
export const getByEmail = (addresses: Address[], email = '') => {
    const cleanEmail = removeEmailAlias(email);
    return addresses.find(({ Email }) => removeEmailAlias(Email) === cleanEmail);
};

/**
 * Check if the address is fallback (Can't receive but has keys)
 */
export const isFallbackAddress = (address?: Address, keys: Key[] = []) =>
    !!address && !address.Receive && !!keys.length;

export const isDirtyAddress = ({ Keys, Status }: Address) => !Keys.length || Status === ADDRESS_STATUS.STATUS_DISABLED;

export const isOwnAddress = (address?: Address, keys: Key[] = []) => !!address && !isFallbackAddress(address, keys);

export const inputToRecipient = (input: string): Recipient => {
    const match = REGEX_RECIPIENT.exec(input);

    if (match !== null) {
        return {
            Name: match[1],
            Address: match[2]
        };
    }
    return {
        Name: input,
        Address: input
    };
};

export const recipientToInput = (recipient: Partial<Recipient> = {}): string => {
    if (recipient.Address && recipient.Name && recipient.Address !== recipient.Name) {
        return `${recipient.Name} <${recipient.Address}>`;
    }

    if (recipient.Address === recipient.Name) {
        return recipient.Address || '';
    }

    return `${recipient.Name} ${recipient.Address}`;
};

export const contactToRecipient = (contact: Partial<ContactEmail> = {}, groupPath?: string): Partial<Recipient> => ({
    Name: contact.Name,
    Address: contact.Email,
    ContactID: contact.ContactID,
    Group: groupPath
});

export const majorToRecipient = (email: string) => ({
    Name: email,
    Address: email
});

export const contactToInput = (contact: Partial<ContactEmail> = {}): string =>
    recipientToInput(contactToRecipient(contact));

export const recipientsWithoutGroup = (recipients: Recipient[], groupPath?: string) =>
    recipients.filter((recipient) => recipient.Group !== groupPath);

export const getRecipientLabelDetailed = (recipient?: Recipient, allContacts?: ContactEmail[]) => {
    const { Name, Address } = recipient || {};
    const contact = getContactOfRecipient(allContacts, Address);
    if (contact) {
        return contact.Name;
    }
    if (Name) {
        return Name;
    }
    return Address;
};

export const getRecipientLabel = (recipient?: Recipient, allContacts?: ContactEmail[]) => {
    const { Name, Address } = recipient || {};
    const contact = getContactOfRecipient(allContacts, Address);
    if (contact) {
        return contact.Name;
    }
    if (!Name || Name === Address) {
        const index = Address?.indexOf('@') || -1;
        if (index === -1) {
            return Address;
        } else {
            return Address?.substring(0, index);
        }
    }
    if (Name) {
        return Name;
    }
    return '';
};

export const getRecipientGroupLabel = (recipientGroup?: RecipientGroup, contactsInGroup = 0) => {
    const count = recipientGroup?.recipients.length;
    const members = c('Info').t`Members`;
    return `${recipientGroup?.group?.Name} (${count}/${contactsInGroup} ${members})`;<commit_msg>Ignore contact names with only spaces<commit_after>import { ADDRESS_STATUS } from 'proton-shared/lib/constants';
import { unique } from 'proton-shared/lib/helpers/array';
import { addPlusAlias, removeEmailAlias } from 'proton-shared/lib/helpers/email';
import { Address, Key } from 'proton-shared/lib/interfaces';
import { Recipient } from 'proton-shared/lib/interfaces/Address';
import { ContactEmail, ContactGroup } from 'proton-shared/lib/interfaces/contacts';
import { c } from 'ttag';
import { RecipientGroup, RecipientOrGroup } from '../models/address';
import { Conversation } from '../models/conversation';
import { Element } from '../models/element';
import { Message } from '../models/message';
import { getContactOfRecipient, getContactsOfGroup } from './contacts';
import { isMessage } from './elements';

export const REGEX_RECIPIENT = /(.*?)\s*<([^>]*)>/;

/**
 * Get address from email
 * Remove + alias and transform to lower case
 */
export const getByEmail = (addresses: Address[], email = '') => {
    const cleanEmail = removeEmailAlias(email);
    return addresses.find(({ Email }) => removeEmailAlias(Email) === cleanEmail);
};

/**
 * Check if the address is fallback (Can't receive but has keys)
 */
export const isFallbackAddress = (address?: Address, keys: Key[] = []) =>
    !!address && !address.Receive && !!keys.length;

export const isDirtyAddress = ({ Keys, Status }: Address) => !Keys.length || Status === ADDRESS_STATUS.STATUS_DISABLED;

export const isOwnAddress = (address?: Address, keys: Key[] = []) => !!address && !isFallbackAddress(address, keys);

export const inputToRecipient = (input: string): Recipient => {
    const match = REGEX_RECIPIENT.exec(input);

    if (match !== null) {
        return {
            Name: match[1],
            Address: match[2]
        };
    }
    return {
        Name: input,
        Address: input
    };
};

export const recipientToInput = (recipient: Partial<Recipient> = {}): string => {
    if (recipient.Address && recipient.Name && recipient.Address !== recipient.Name) {
        return `${recipient.Name} <${recipient.Address}>`;
    }

    if (recipient.Address === recipient.Name) {
        return recipient.Address || '';
    }

    return `${recipient.Name} ${recipient.Address}`;
};

export const contactToRecipient = (contact: Partial<ContactEmail> = {}, groupPath?: string): Partial<Recipient> => ({
    Name: contact.Name,
    Address: contact.Email,
    ContactID: contact.ContactID,
    Group: groupPath
});

export const majorToRecipient = (email: string) => ({
    Name: email,
    Address: email
});

export const contactToInput = (contact: Partial<ContactEmail> = {}): string =>
    recipientToInput(contactToRecipient(contact));

export const recipientsWithoutGroup = (recipients: Recipient[], groupPath?: string) =>
    recipients.filter((recipient) => recipient.Group !== groupPath);

export const getRecipientLabelDetailed = (recipient?: Recipient, allContacts?: ContactEmail[]) => {
    const { Name, Address } = recipient || {};
    const contact = getContactOfRecipient(allContacts, Address);

    if (contact?.Name?.trim()) {
        return contact.Name;
    }
    if (Name) {
        return Name;
    }
    return Address;
};

export const getRecipientLabel = (recipient?: Recipient, allContacts?: ContactEmail[]) => {
    const { Name, Address } = recipient || {};
    const contact = getContactOfRecipient(allContacts, Address);

    if (contact?.Name?.trim()) {
        return contact.Name;
    }
    if (!Name || Name === Address) {
        const index = Address?.indexOf('@') || -1;
        if (index === -1) {
            return Address;
        } else {
            return Address?.substring(0, index);
        }
    }
    if (Name) {
        return Name;
    }
    return '';
};

export const getRecipientGroupLabel = (recipientGroup?: RecipientGroup, contactsInGroup = 0) => {
    const count = recipientGroup?.recipients.length;
    const members = c('Info').t`Members`;
    return `${recipientGroup?.group?.Name} (${count}/${contactsInGroup} ${members})`;
{'fraction_non_alphanumeric': 0.1534090909090909, 'fraction_numerical': 0.0014822134387351778, 'mean_word_length': 3.600568181818182, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 47, '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': '2131894', 'n_tokens_mistral': 2394, 'n_tokens_neox': 2346, 'n_words': 594}