138 lines
3.2 KiB
TypeScript
138 lines
3.2 KiB
TypeScript
const twoMinutes = 120000;
|
|
|
|
interface DesignProject {
|
|
category: string;
|
|
editor: string;
|
|
language: string;
|
|
project: string;
|
|
}
|
|
|
|
const parseCanva = (): DesignProject | undefined => {
|
|
const projectName = (document.head.querySelector('meta[property="og:title"]') as HTMLMetaElement)
|
|
.content;
|
|
if (!projectName) return;
|
|
|
|
// make sure the page title matches the design input element's value, meaning this is a design file
|
|
const canvaProjectInput = Array.from(
|
|
document.querySelector('nav')?.querySelectorAll('input') ?? [],
|
|
).find((inp) => inp.value === projectName);
|
|
if (!canvaProjectInput) return;
|
|
|
|
return {
|
|
category: 'designing',
|
|
editor: 'Canva',
|
|
language: 'Canva Design',
|
|
project: projectName,
|
|
};
|
|
};
|
|
|
|
const parseFigma = (): DesignProject | undefined => {
|
|
const figmaProject = document.getElementsByClassName('gpu-view-content');
|
|
if (figmaProject.length === 0) return;
|
|
|
|
const projectName = (document.querySelector('span[data-testid="filename"]') as HTMLElement)
|
|
.innerText;
|
|
return {
|
|
category: 'designing',
|
|
editor: 'Figma',
|
|
language: 'Figma Design',
|
|
project: projectName,
|
|
};
|
|
};
|
|
|
|
const parseMeet = (): DesignProject | undefined => {
|
|
const meetId = document.querySelector('[data-meeting-title]')?.getAttribute('data-meeting-title');
|
|
if (!meetId) {
|
|
return;
|
|
}
|
|
return {
|
|
category: 'meeting',
|
|
editor: 'Meet',
|
|
language: 'Google Meet',
|
|
project: meetId,
|
|
};
|
|
};
|
|
|
|
const getParser: {
|
|
[key: string]:
|
|
| (() => { editor: string; language: string; project: string } | undefined)
|
|
| undefined;
|
|
} = {
|
|
'meet.google.com': parseMeet,
|
|
'www.canva.com': parseCanva,
|
|
'www.figma.com': parseFigma,
|
|
};
|
|
|
|
const init = async () => {
|
|
const { hostname } = document.location;
|
|
|
|
const projectDetails = getParser[hostname]?.();
|
|
if (projectDetails) {
|
|
chrome.runtime.sendMessage({ projectDetails, recordHeartbeat: true });
|
|
}
|
|
};
|
|
|
|
function debounce(func: () => void, timeout = twoMinutes) {
|
|
let timer: NodeJS.Timeout | undefined;
|
|
return () => {
|
|
if (timer) {
|
|
return;
|
|
}
|
|
func();
|
|
timer = setTimeout(() => {
|
|
clearTimeout(timer);
|
|
timer = undefined;
|
|
}, timeout);
|
|
};
|
|
}
|
|
|
|
document.body.addEventListener(
|
|
'click',
|
|
debounce(() => init()),
|
|
true,
|
|
);
|
|
|
|
document.body.addEventListener(
|
|
'keypress',
|
|
debounce(() => init()),
|
|
true,
|
|
);
|
|
|
|
chrome.runtime.onMessage.addListener((request: { message: string }, sender, sendResponse) => {
|
|
if (request.message === 'get_html') {
|
|
sendResponse({ html: document.documentElement.outerHTML });
|
|
}
|
|
});
|
|
|
|
// Google Meet
|
|
// https://meet.google.com/jzf-bwrz-djk
|
|
if (window.location.href.startsWith('https://meet.google.com/')) {
|
|
// In google meet website
|
|
|
|
let inMeeting = false;
|
|
|
|
const checkIfInAMeeting = (ms: number) => {
|
|
setTimeout(() => {
|
|
const isMeetingPage = !!document.querySelector('[data-meeting-title]');
|
|
|
|
if (isMeetingPage) {
|
|
void init();
|
|
inMeeting = true;
|
|
|
|
// If already in a meeting then check again after 2min
|
|
checkIfInAMeeting(1000 * 60 * 2);
|
|
} else {
|
|
if (inMeeting) {
|
|
void init();
|
|
inMeeting = false;
|
|
}
|
|
|
|
// If not in a meeting then check again after 5s
|
|
checkIfInAMeeting(1000 * 5);
|
|
}
|
|
}, ms);
|
|
};
|
|
|
|
checkIfInAMeeting(0);
|
|
}
|