Files
twenty/packages/twenty-chrome-extension/src/background/index.ts
Abdullah 1265dc74d0 Closes #2413 - Building a chrome extension for twenty to store person/company data into a workspace. (#3430)
* build: create a new vite project for chrome extension

* feat: configure theme per the frontend codebase for chrome extension

* feat: inject the add to twenty button into linkedin profile page

* feat: create the api key form ui and render it on the options page

* feat: inject the add to twenty button into linkedin company page

* feat: scrape required data from both the user profile and the company profile

* refactor: move modules into options because it is the only page using react for now

* fix: show add to twenty button without having to reload the single page application

* fix: extract domain of the business website instead of scrapping the industry type

* feat: store api key to local storage and open options page when trying to store data without setting a key

* feat: send data to the backend upon click and store it to the database

* fix: open options page upon clicking the extension icon

* fix: update terminology from user to person to match the codebase convention

* fix: adopt chrome extension to monorepo approach using nx and get the development server working

* fix: update vite config for build command to work per the requirement

* feat: add instructions in the readme file to install the extension for local testing

* fix: move server base url to a dotenv file and replace the hard-coded url

* feat: permit user to configure a custom route for the server from the options page

* fix: fetch api key and route from local storage and display on options page to inform users of their choices

* fix: move front base url to dotenv and replace the hard-coded url

* fix: remove the trailing slash from person and company linkedin username

* fix: improve code commenting to explain implementation somewhat better

* ci: introduce a workflow to build chrome extension to ensure it can be published

* fix: format files to display code in a consistent manner per the prettier configuration in codebase

* fix: improve the commenting significantly to explain important and hard-to-understand parts of the code

* fix: remove unused permissions from the manifest file for publishing to the chrome web store

* Add nx

* Fix vale

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-02-12 12:30:23 +01:00

63 lines
2.9 KiB
TypeScript

import { openOptionsPage } from './utils/openOptionsPage';
console.log('Background Script Works');
// Open options page programmatically in a new tab.
chrome.runtime.onInstalled.addListener(function (details) {
if (details.reason === 'install') {
openOptionsPage();
}
});
// Open options page when extension icon is clicked.
chrome.action.onClicked.addListener(function () {
openOptionsPage();
});
// This listens for an event from other parts of the extension, such as the content script, and performs the required tasks.
// The cases themselves are labelled such that their operations are reflected by their names.
chrome.runtime.onMessage.addListener((message, _, sendResponse) => {
switch (message.action) {
case 'getActiveTabUrl': // e.g. "https://linkedin.com/company/twenty/"
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs && tabs[0]) {
const activeTabUrl: string | undefined = tabs[0].url;
sendResponse({ url: activeTabUrl });
}
});
break;
case 'openOptionsPage':
openOptionsPage();
break;
default:
break;
}
return true;
});
// Keep track of the tabs in which the "Add to Twenty" button has already been injected.
// Could be that the content script is executed at "https://linkedin.com/feed/", but is needed at "https://linkedin.com/in/mabdullahabaid/".
// However, since Linkedin is a SPA, the script would not be re-executed when you navigate to "https://linkedin.com/in/mabdullahabaid/" from a user action.
// Therefore, this tracks if the user is on desired route and then re-executes the content script to create the "Add to Twenty" button.
// We use a "Set" to keep track of tab ids because it could be that the "Add to Twenty" button was created at "https://linkedin/com/company/twenty".
// However, when we change to about on the company page, the url becomes "https://www.linkedin.com/company/twenty/about/" and the button is created again.
// This creates a duplicate button, which we want to avoid. So, we instruct the extension to only create the button once for any of the following urls.
// "https://www.linkedin.com/company/twenty/" "https://www.linkedin.com/company/twenty/about/" "https://www.linkedin.com/company/twenty/people/".
const injectedTabs: Set<number> = new Set();
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
const isDesiredRoute =
tab.url?.match(/^https?:\/\/(?:www\.)?linkedin\.com\/company(?:\/\S+)?/) ||
tab.url?.match(/^https?:\/\/(?:www\.)?linkedin\.com\/in(?:\/\S+)?/);
if (changeInfo.status === 'complete' && tab.active) {
if (isDesiredRoute && !injectedTabs.has(tabId)) {
chrome.tabs.sendMessage(tabId, { action: 'executeContentScript' });
injectedTabs.add(tabId);
} else if (!isDesiredRoute) {
injectedTabs.delete(tabId); // Clear entry if navigated away from LinkedIn company page.
}
}
});