Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firefox fix #61

Merged
merged 12 commits into from
Jul 16, 2024
Merged
8,256 changes: 4,698 additions & 3,558 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"packageManager": "[email protected]",
"scripts": {
"dev": "plasmo dev",
"dev:firefox": "plasmo dev --target=firefox-mv3",
"build": "plasmo build",
"package": "plasmo package",
"format": "prettier --write .",
Expand All @@ -20,7 +21,7 @@
"@plasmohq/storage": "^1.3.1",
"apexcharts": "^3.37.1",
"next": "^13.1.5",
"plasmo": "^0.67.3",
"plasmo": "^0.85.2",
"react": "18.2.0",
"react-apexcharts": "^1.4.0",
"react-dom": "18.2.0",
Expand Down Expand Up @@ -104,9 +105,9 @@
"nativeMessaging"
],
"host_permissions": [
"https://utdallas.collegescheduler.com/terms/*/courses/*",
"https://www.ratemyprofessors.com/",
"https://trends.utdnebula.com/"
"https://utdallas.collegescheduler.com/*",
"https://www.ratemyprofessors.com/*",
"https://trends.utdnebula.com/*"
],
"browser_specific_settings": {
"gecko": {
Expand Down
49 changes: 35 additions & 14 deletions src/background.ts → src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Storage } from '@plasmohq/storage';

import { CourseHeader, listenForTableChange, scrapeCourseData } from '~content';
import { neededOrigins } from '~data/config';

export interface ShowCourseTabPayload {
header: CourseHeader;
Expand All @@ -14,15 +15,17 @@ let scrapedCourseData: ShowCourseTabPayload = null;
// for persistent state
const storage = new Storage();

const realBrowser = process.env.PLASMO_BROWSER === 'chrome' ? chrome : browser;

/** Injects the content script if we hit a course page */
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
realBrowser.webNavigation.onHistoryStateUpdated.addListener((details) => {
if (
/^.*:\/\/utdallas\.collegescheduler\.com\/terms\/.*\/courses\/.+$/.test(
details.url,
)
) {
//Scrape data
chrome.scripting.executeScript(
realBrowser.scripting.executeScript(
{
target: {
tabId: details.tabId,
Expand All @@ -40,28 +43,28 @@ chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
},
);
//Listen for table change to rescrape data
chrome.tabs.sendMessage(details.tabId, 'disconnectObserver');
chrome.scripting.executeScript({
realBrowser.tabs.sendMessage(details.tabId, 'disconnectObserver');
realBrowser.scripting.executeScript({
target: {
tabId: details.tabId,
},
func: listenForTableChange,
});
//Store tab info
chrome.action.setBadgeText({ text: '!' });
chrome.action.setBadgeBackgroundColor({ color: 'green' });
realBrowser.action.setBadgeText({ text: '!' });
realBrowser.action.setBadgeBackgroundColor({ color: 'green' });
courseTabId = details.tabId;
storage.set('courseTabId', courseTabId);
storage.set('courseTabUrl', details.url);
} else {
chrome.action.setBadgeText({ text: '' });
realBrowser.action.setBadgeText({ text: '' });
}
});

/** Rescrape data on table change */
chrome.runtime.onMessage.addListener(function (message) {
realBrowser.runtime.onMessage.addListener(function (message) {
if (message === 'tableChange') {
chrome.scripting.executeScript(
realBrowser.scripting.executeScript(
{
target: {
tabId: courseTabId,
Expand All @@ -80,14 +83,32 @@ chrome.runtime.onMessage.addListener(function (message) {
});

/** Sets the icon to be active if we're on a course tab */
chrome.tabs.onActivated.addListener(async () => {
realBrowser.tabs.onActivated.addListener(async () => {
const cachedTabUrl: string = await storage.get('courseTabUrl');
const currentTabUrl: string = (await getCurrentTab()).url;
if (cachedTabUrl === currentTabUrl) {
chrome.action.setBadgeText({ text: '!' });
chrome.action.setBadgeBackgroundColor({ color: 'green' });
realBrowser.action.setBadgeText({ text: '!' });
realBrowser.action.setBadgeBackgroundColor({ color: 'green' });
} else {
chrome.action.setBadgeText({ text: '' });
realBrowser.action.setBadgeText({ text: '' });
}
});

realBrowser.runtime.onInstalled.addListener(async () => {
const currentPermissions: { permissions: string[]; origins: string[] } =
await realBrowser.permissions.getAll();
if (
neededOrigins.filter(
(origin) => !currentPermissions.origins.includes(origin),
).length !== 0
) {
const popupURL = await realBrowser.runtime.getURL('tabs/permissions.html');
realBrowser.windows.create({
url: popupURL,
type: 'popup',
width: 550,
height: 250,
});
}
});

Expand All @@ -103,6 +124,6 @@ export async function getScrapedCourseData() {
async function getCurrentTab() {
const queryOptions = { active: true, lastFocusedWindow: true };
// `tab` will either be a `tabs.Tab` instance or `undefined`.
const [tab] = await chrome.tabs.query(queryOptions);
const [tab] = await realBrowser.tabs.query(queryOptions);
return tab;
}
2 changes: 1 addition & 1 deletion src/background/messages/getScrapeData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PlasmoMessaging } from '@plasmohq/messaging';

import { getScrapedCourseData } from '../../background';
import { getScrapedCourseData } from '..';

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
const data = await getScrapedCourseData();
Expand Down
10 changes: 7 additions & 3 deletions src/content.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { PlasmoCSConfig } from 'plasmo';

export interface CourseHeader {
subjectPrefix: string;
courseNumber: string;
}

// Plasmo CS config export
export const config = {
export const config: PlasmoCSConfig = {
matches: ['https://utdallas.collegescheduler.com/terms/*/courses/*'],
world: 'MAIN',
};

/**
Expand Down Expand Up @@ -97,6 +100,7 @@ export async function scrapeCourseData() {
}
}

const realBrowser = process.env.PLASMO_BROWSER === 'chrome' ? chrome : browser;
/** This listens for clicks on the buttons that switch between the enabled and disabled professor tabs and reports back to background.ts */
export function listenForTableChange() {
const observer = new MutationObserver((mutationsList) => {
Expand All @@ -107,7 +111,7 @@ export function listenForTableChange() {
) {
//button corresponding to shown table is given an active class
if (mutation.target.classList.contains('active')) {
chrome.runtime.sendMessage('tableChange');
realBrowser.runtime.sendMessage('tableChange');
}
}
}
Expand All @@ -117,7 +121,7 @@ export function listenForTableChange() {
subtree: true,
});
//remove observer when ordered by backgroud.ts to avoid duplicates
chrome.runtime.onMessage.addListener(function (message) {
realBrowser.runtime.onMessage.addListener(function (message) {
if (message === 'disconnectObserver') {
observer.disconnect();
}
Expand Down
6 changes: 6 additions & 0 deletions src/data/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ export const PROFESSOR_QUERY = {

export const SCHOOL_ID = '1273';
export const RMP_GRAPHQL_URL = 'https://www.ratemyprofessors.com/graphql';

export const neededOrigins = [
'https://utdallas.collegescheduler.com/*',
'https://www.ratemyprofessors.com/*',
'https://trends.utdnebula.com/*',
];
2 changes: 1 addition & 1 deletion src/pages/CoursePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Landing } from '~components/Landing';
import { MiniProfessor } from '~components/MiniProfessor';
import {
buildProfessorProfile,
ProfessorProfileInterface,
type ProfessorProfileInterface,
} from '~data/builder';

// Example of how to fetch the scraped data from the background script, given that it exists
Expand Down
21 changes: 21 additions & 0 deletions src/popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ import React from 'react';
import { MemoryRouter } from 'react-router-dom';

import { Routing } from '~/pages';
import { neededOrigins } from '~data/config';

const realBrowser = process.env.PLASMO_BROWSER === 'chrome' ? chrome : browser;
async function checkPermissions() {
const currentPermissions: { permissions: string[]; origins: string[] } =
await realBrowser.permissions.getAll();
if (
neededOrigins.filter(
(origin) => !currentPermissions.origins.includes(origin),
).length !== 0
) {
const popupURL = await realBrowser.runtime.getURL('tabs/permissions.html');
realBrowser.windows.create({
url: popupURL,
type: 'popup',
width: 550,
height: 250,
});
}
}
checkPermissions();

function IndexPopup() {
return (
Expand Down
41 changes: 41 additions & 0 deletions src/tabs/permissions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import '~/style.css';

import React, { useState } from 'react';

import { neededOrigins } from '~data/config';

const realBrowser = process.env.PLASMO_BROWSER === 'chrome' ? chrome : browser;

function PermissionsPls() {
const [granted, setGranted] = useState(false);

return (
<div>
<h1>Sk.edge needs permissions to run</h1>
<p>
We need access to Schedule Planner and the sources we get our data from.
</p>
<h2>Please click the button below to grant permissions.</h2>
<button
className="p-2 bg-blue-dark text-white rounded-lg"
onClick={async () => {
const response = await realBrowser.permissions.request({
origins: neededOrigins,
});
if (response) {
setGranted(true);
}
}}
>
Request permissions
</button>
{granted && (
<p>
Thank you!
<br /> You can close this window now.
</p>
)}
</div>
);
}
export default PermissionsPls;
Loading