refactoring, using different pattern for page injection and reusing same pattern for both popup and content scripts
This commit is contained in:
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'));
|
||||
@@ -1,24 +0,0 @@
|
||||
// this is a custom wrapper around react-devtools
|
||||
// that changes it so that we only send messages to the devtools when the current tab is active;
|
||||
import { connectToDevTools } from 'react-devtools-core';
|
||||
|
||||
// connect to the devtools server
|
||||
let ws = new WebSocket('ws://localhost:8097');
|
||||
|
||||
connectToDevTools({
|
||||
websocket: ws,
|
||||
});
|
||||
|
||||
// when the tab's visibile state changes, we connect or disconnect from the devtools
|
||||
const onVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
ws = new WebSocket('ws://localhost:8097');
|
||||
connectToDevTools({
|
||||
websocket: ws,
|
||||
});
|
||||
} else {
|
||||
ws.close();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
Reference in New Issue
Block a user