Pin more than 3 Whatsapp contacts
Published: 2024-04-09 04:25:48

I am working on a chrome extension which involves DOM manipulation for adding pin button for pinnedContacts iterating the array, the button needs to be added for each contact name in the list, Then need to move on to the top of the chat list.

The problem is the index for each chat item dynamically changing, so while trying to apply the logic in the pinned contact, the feature doe not retain, keeps changing while scrolling up or down.

We are using HTML, CSS, Javascript for the extension. here is the javascript code for retrieving pinned contacts and add pin button.


Could any one please help me to resolve the issue.


const getPinnedContacts = () => {
    return new Promise((resolve, reject) => {
        chrome.storage.sync.get("pinnedContacts", (data) => {
            if (chrome.runtime.lastError) {
                reject(chrome.runtime.lastError);
            } else {
                const pinnedContacts = (data && data.pinnedContacts) || [];
                resolve(pinnedContacts);
            }
        });
    });
};

const getChatList = () => {
    return new Promise((resolve) => {
        const chatList = document.querySelector('[aria-label="Chat list"]');
        if (chatList) {
            resolve(chatList);
        } else {
            // Retry after 1 second if chat list element is not found
            setTimeout(() => {
                getChatList().then(resolve);
            }, 1000);
        }
    });
};

const waitForChatList = () => {
    const chatList = document.querySelector('[aria-label="Chat list"]');
    if (chatList) {
        // Retrieve pinned contacts
        chrome.storage.sync.get("pinnedContacts", (data) => {
            const pinnedContacts = (data && data.pinnedContacts) || [];
            // Process chat list and add pin buttons
            processChatList(chatList, pinnedContacts);
        });
    } else {
        // Chat list element not found, wait and retry
        setTimeout(waitForChatList, 1000); // Retry after 1 second
    }
};

// Initial call to start processing
waitForChatList();

const processChatListSortPinnedContacts = () => {
    const waitForChatList = () => {
        const chatList = document.querySelector('[aria-label="Chat list"]');
        if (chatList) {
            // Retrieve pinned contacts
            chrome.storage.sync.get("pinnedContacts", (data) => {
                const pinnedContacts = (data && data.pinnedContacts) || [];
                // Process chat list and add pin buttons
                processChatList(chatList, pinnedContacts);
            });
        } else {
            // Chat list element not found, wait and retry
            setTimeout(waitForChatList, 1000); // Retry after 1 second
        }
    };

    // Initial call to start processing
    waitForChatList();
};


const processChatList = async (chatList, pinnedContacts) => {

    const chatContacts = chatList.querySelectorAll('div[role="listitem"]');

    const contactNames = [];
    const pinnedContactElementsMap = new Map();

    pinnedContacts.forEach(pinnedContact => {

        chatContacts.forEach((contact, index)  => {
         //console.log("chat contacts  "+contact.innerHTML+"  index :  "+index);
            const nthChild = index + 1; 
            try {
            const titleElements = contact.querySelectorAll(`#pane-side > div:nth-child(3) > div > div > div:nth-child(${nthChild}) > div > div > div > div._ak8l > div._ak8o > div._ak8q > div`);
            
           // console.log("titleElements len "+titleElements.length);

            if(titleElements.length>0)
            {
                //console.log("titleElements 0 "+titleElements[0].innerHTML);
                const titleElement1 = titleElements[0].querySelector('span');

                console.log("titleElement 1 "+titleElement1.textContent.trim());
                console.log("pinnedContact  "+pinnedContact);
                console.log("pinnedContact matched "+(pinnedContact === titleElement1.textContent.trim()));
                    if(pinnedContact === titleElement1.textContent.trim()) {

                        console.log("gridCellElement required 111 ");
                    const gridCellElement = contact.querySelector(`#pane-side > div:nth-child(3) > div > div > div:nth-child(${nthChild}) > div > div > div > div._ak8l > div._ak8j > div._ak8i`);
                
                    const pinButton = gridCellElement.querySelector('span[data-icon="pinned2"]');

                        if (!pinButton ) {
                            const gridCellElement = contact.querySelector(`#pane-side > div:nth-child(3) > div > div > div:nth-child(${nthChild}) > div > div > div > div._ak8l > div._ak8j > div._ak8i`);
                    
                            // Create a new pin button
                            const newPinButton = document.createElement('div');
                            newPinButton.className = '_ahlk _ahll';
                            newPinButton.innerHTML = '<span data-icon="pinned2"><svg height="15" width="13" preserveAspectRatio="xMidYMid meet" class=""><title>pinned2</title><path fill="currentColor" d="M12.074 4.21 8.7 8.232l.116 4.233a.4.4 0 0 1-.657.318L.43 6.297a.4.4 0 0 1 .199-.702l4.196-.622L8.196.957a.63.63 0 0 1 .887-.078l2.914 2.445a.63.63 0 0 1 .077.887ZM1.294 14.229a.713.713 0 0 1-1.09-.915l2.674-3.64 1.536 1.288-3.12 3.267Z"></path></svg></span>';
                            
                            // Find the span element within the grid cell element
                            const spanElement = gridCellElement.querySelector('span');
                            if (spanElement) {
                                // Insert the new pin button after the span element
                                spanElement.insertAdjacentElement('afterend', newPinButton);
                            }
                            return;
                        }
                }
            }
            else {
                const titleElement2 = contact.querySelector(`#pane-side > div:nth-child(3) > div > div > div:nth-child(${nthChild}) > div > div > div > div._ak8l > div._ak8o > div._ak8q > div > span[title=${pinnedContact}]`);
               // console.log("titleElement 2 "+titleElement2.innerHTML);
                if(titleElement2)
                {
                    console.log("gridCellElement required 222 ");
                const gridCellElement = contact.querySelector(`#pane-side > div:nth-child(3) > div > div > div:nth-child(${nthChild}) > div > div > div > div._ak8l > div._ak8j > div._ak8i`);
                
                    const pinButton = gridCellElement.querySelector('span[data-icon="pinned2"]');

                    if (!pinButton) {
                        // Create a new pin button
                        const newPinButton = document.createElement('div');
                        newPinButton.className = '_ahlk _ahll';
                        newPinButton.innerHTML = '<span data-icon="pinned2"><svg height="15" width="13" preserveAspectRatio="xMidYMid meet" class=""><title>pinned2</title><path fill="currentColor" d="M12.074 4.21 8.7 8.232l.116 4.233a.4.4 0 0 1-.657.318L.43 6.297a.4.4 0 0 1 .199-.702l4.196-.622L8.196.957a.63.63 0 0 1 .887-.078l2.914 2.445a.63.63 0 0 1 .077.887ZM1.294 14.229a.713.713 0 0 1-1.09-.915l2.674-3.64 1.536 1.288-3.12 3.267Z"></path></svg></span>';
                        
                        // Find the span element within the grid cell element
                        const spanElement = gridCellElement.querySelector('span');
                        if (spanElement) {
                            // Insert the new pin button after the span element
                            spanElement.insertAdjacentElement('afterend', newPinButton);
                        }
                        return;
                    }
                }
            }
            } catch (error) {
                //console.error('Error while querying selector:', error);
                // Handle the error as needed
            }
        });
});
    await new Promise(resolve => setTimeout(resolve, 0));

    const pinnedContactEntries = Array.from(pinnedContactElementsMap.entries());

    console.log("pinnedContactEntries Element:"+ pinnedContactEntries);
   
    chrome.storage.sync.set({ contactNames: contactNames });
};

processChatListSortPinnedContacts();