refactoring, using different pattern for page injection and reusing same pattern for both popup and content scripts
This commit is contained in:
11
package-lock.json
generated
11
package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"chrome-extension-toolkit": "^0.0.22",
|
||||
"classnames": "^2.3.2",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -4702,6 +4703,11 @@
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||
},
|
||||
"node_modules/clean-css": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
|
||||
@@ -20674,6 +20680,11 @@
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"chrome-extension-toolkit": "^0.0.22",
|
||||
"classnames": "^2.3.2",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
||||
16
src/views/components/CourseCatalogMain.tsx
Normal file
16
src/views/components/CourseCatalogMain.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { bMessenger } from 'src/shared/messages';
|
||||
import { SiteSupport } from '../lib/getSiteSupport';
|
||||
import { Button } from './common/Button/Button';
|
||||
|
||||
interface Props {
|
||||
support: SiteSupport[];
|
||||
}
|
||||
|
||||
export default function CourseCatalogMain(props: Props) {
|
||||
const openGoogle = () => {
|
||||
bMessenger.openNewTab({ url: 'https://google.com' });
|
||||
};
|
||||
|
||||
return <Button onClick={openGoogle}>{props.support.join(',')}</Button>;
|
||||
}
|
||||
14
src/views/components/common/Button/Button.tsx
Normal file
14
src/views/components/common/Button/Button.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import styles from './Button.module.scss';
|
||||
|
||||
interface Props {
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export function Button(props: React.PropsWithChildren<Props>): JSX.Element {
|
||||
return (
|
||||
<button className={styles.button} onClick={props.onClick}>
|
||||
{props.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function ContentMain() {
|
||||
return <div>content</div>;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react';
|
||||
import { bMessenger } from 'src/shared/messages';
|
||||
import styles from './Button.module.scss';
|
||||
|
||||
export function Button(): JSX.Element {
|
||||
const handleOpenUrl = (url: string) => () => {
|
||||
bMessenger.openNewTab({ url });
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={styles.button} onClick={handleOpenUrl('https://www.google.com')}>
|
||||
Click me
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { ContextInvalidated, createShadowDOM, onContextInvalidated } from 'chrome-extension-toolkit';
|
||||
import ContentMain from './ContentMain';
|
||||
import colors from '../styles/colors.module.scss';
|
||||
import getPageTypes, { PageType } from './lib/getPageTypes';
|
||||
import { populateSearchInputs } from './lib/courseSchedule/populateSearchInputs';
|
||||
|
||||
const pageTypes = getPageTypes(window.location.href);
|
||||
console.log('pageTypes:', pageTypes);
|
||||
|
||||
if (pageTypes.includes(PageType.COURSE_SCHEDULE)) {
|
||||
if (pageTypes.includes(PageType.COURSE_SCHEDULE_LIST)) {
|
||||
populateSearchInputs();
|
||||
}
|
||||
const shadowDom = createShadowDOM('ut-registration-plus-dom-container');
|
||||
render(<ContentMain />, shadowDom.shadowRoot);
|
||||
shadowDom.addStyle('static/css/content.css');
|
||||
}
|
||||
|
||||
onContextInvalidated(() => {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'context-invalidated-container';
|
||||
document.body.appendChild(div);
|
||||
render(
|
||||
<ContextInvalidated fontFamily='monospace' color={colors.WHITE} backgroundColor={colors.BURNT_ORANGE} />,
|
||||
div
|
||||
);
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
export enum PageType {
|
||||
EXTENSION_POPUP,
|
||||
COURSE_SCHEDULE,
|
||||
COURSE_SCHEDULE_LIST,
|
||||
COURSE_DETAILS,
|
||||
UT_PLANNER,
|
||||
WAITLIST,
|
||||
}
|
||||
|
||||
/**
|
||||
* We use this function to determine what page the user is on, and then we can use that information to determine what to do
|
||||
* @param url the url of the current page
|
||||
* @returns a list of page types that the current page is
|
||||
*/
|
||||
export default function getPageTypes(url: string): PageType[] {
|
||||
if (url.includes('chrome-extension://')) {
|
||||
return [PageType.EXTENSION_POPUP];
|
||||
}
|
||||
if (url.includes('utexas.collegescheduler.com')) {
|
||||
return [PageType.UT_PLANNER];
|
||||
}
|
||||
if (url.includes('utdirect.utexas.edu/apps/registrar/course_schedule')) {
|
||||
const types = [PageType.COURSE_SCHEDULE];
|
||||
if (url.includes('results')) {
|
||||
types.push(PageType.COURSE_SCHEDULE_LIST);
|
||||
}
|
||||
if (document.querySelector('#details')) {
|
||||
types.push(PageType.COURSE_DETAILS);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
|
||||
return [PageType.WAITLIST];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
37
src/views/index.tsx
Normal file
37
src/views/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { ContextInvalidated, createShadowDOM, isExtensionPopup, onContextInvalidated } from 'chrome-extension-toolkit';
|
||||
import CourseCatalogMain from './components/CourseCatalogMain';
|
||||
import colors from './styles/colors.module.scss';
|
||||
import getSiteSupport, { SiteSupport } from './lib/getSiteSupport';
|
||||
import PopupMain from './components/PopupMain';
|
||||
|
||||
const support = getSiteSupport(window.location.href);
|
||||
|
||||
if (isExtensionPopup()) {
|
||||
render(<PopupMain />, document.getElementById('root'));
|
||||
}
|
||||
|
||||
if (support.includes(SiteSupport.COURSE_CATALOG)) {
|
||||
const shadowDom = createShadowDOM('ut-registration-plus-dom-container');
|
||||
render(<CourseCatalogMain support={support} />, shadowDom.shadowRoot);
|
||||
shadowDom.addStyle('static/css/content.css');
|
||||
}
|
||||
|
||||
if (support.includes(SiteSupport.WAITLIST)) {
|
||||
// TODO: Implement waitlist support
|
||||
}
|
||||
|
||||
if (support.includes(SiteSupport.UT_PLANNER)) {
|
||||
// TODO: Implement ut planner support
|
||||
}
|
||||
|
||||
onContextInvalidated(() => {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'context-invalidated-container';
|
||||
document.body.appendChild(div);
|
||||
render(
|
||||
<ContextInvalidated fontFamily='monospace' color={colors.WHITE} backgroundColor={colors.BURNT_ORANGE} />,
|
||||
div
|
||||
);
|
||||
});
|
||||
36
src/views/lib/getSiteSupport.ts
Normal file
36
src/views/lib/getSiteSupport.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* An enum that represents the different types of pages that we support
|
||||
* a given url/page can correspond to many of these enum values
|
||||
*/
|
||||
export enum SiteSupport {
|
||||
COURSE_CATALOG = 'COURSE_CATALOG',
|
||||
COURSE_CATALOG_LIST = 'COURSE_CATALOG_LIST',
|
||||
COURSE_CATALOG_DETAILS = 'COURSE_CATALOG_DETAILS',
|
||||
UT_PLANNER = 'UT_PLANNER',
|
||||
WAITLIST = 'WAITLIST',
|
||||
}
|
||||
|
||||
/**
|
||||
* We use this function to determine what page the user is on, and then we can use that information to determine what to do
|
||||
* @param url the url of the current page
|
||||
* @returns a list of page types that the current page is
|
||||
*/
|
||||
export default function getSiteSupport(url: string): SiteSupport[] {
|
||||
if (url.includes('utexas.collegescheduler.com')) {
|
||||
return [SiteSupport.UT_PLANNER];
|
||||
}
|
||||
if (url.includes('utdirect.utexas.edu/apps/registrar/course_schedule')) {
|
||||
const types = [SiteSupport.COURSE_CATALOG];
|
||||
if (url.includes('results')) {
|
||||
types.push(SiteSupport.COURSE_CATALOG_LIST);
|
||||
}
|
||||
if (document.querySelector('#details')) {
|
||||
types.push(SiteSupport.COURSE_CATALOG_DETAILS);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
if (url.includes('utdirect.utexas.edu') && (url.includes('waitlist') || url.includes('classlist'))) {
|
||||
return [SiteSupport.WAITLIST];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import PopupMain from './PopupMain';
|
||||
|
||||
render(<PopupMain />, document.getElementById('root'));
|
||||
@@ -26,9 +26,9 @@ export default function config(mode: Environment, manifest: chrome.runtime.Manif
|
||||
|
||||
// the entry points for the extension (the files that webpack will start bundling from)
|
||||
const entry: Entries = {
|
||||
content: [path.resolve('src', 'views', 'content', 'content')],
|
||||
content: [path.resolve('src', 'views')],
|
||||
popup: [path.resolve('src', 'views')],
|
||||
background: [path.resolve('src', 'background', 'background')],
|
||||
popup: [path.resolve('src', 'views', 'popup', 'popup')],
|
||||
};
|
||||
|
||||
// the entries that need an html file to be generated
|
||||
@@ -39,8 +39,8 @@ export default function config(mode: Environment, manifest: chrome.runtime.Manif
|
||||
entry.debug = [path.resolve('src', 'debug')];
|
||||
|
||||
// we need to import react-devtools before the react code in development
|
||||
entry.content = [path.resolve('src', 'views', 'reactDevtools'), ...entry.content];
|
||||
entry.popup = [path.resolve('src', 'views', 'reactDevtools'), ...entry.popup];
|
||||
entry.content = [path.resolve('src', 'debug', 'reactDevtools'), ...entry.content];
|
||||
entry.popup = [path.resolve('src', 'debug', 'reactDevtools'), ...entry.popup];
|
||||
}
|
||||
|
||||
/** @see https://webpack.js.org/configuration for documentation */
|
||||
|
||||
Reference in New Issue
Block a user