Merge pull request #6 from SethBurkart123/dev

Merge DEV (new popup) into main
This commit is contained in:
Seth Burkart
2023-09-25 11:44:39 +10:00
committed by GitHub
45 changed files with 1061 additions and 400 deletions
+1
View File
@@ -1,6 +1,7 @@
# npm # npm
node_modules/ node_modules/
package-lock.json package-lock.json
bun.lockb
# Build # Build
package.zip package.zip
+3
View File
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
BIN
View File
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
overrides: [
{
files: ['*.ts', '*.tsx'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
],
}
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
.dark .switch[data-ison=true],.switch[data-ison=true]{background-color:#30d259}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+15
View File
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<script type="module" crossorigin src="/client/public/client.js"></script>
<link rel="stylesheet" href="/client/rsc/css/index.css">
</head>
<body class="">
<div id="ExtensionPopup"></div>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body class="">
<div id="ExtensionPopup"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
{
"name": "popup",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite build --watch",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@types/chrome": "^0.0.246",
"framer-motion": "^10.16.4",
"react": "^18.2.0",
"react-best-gradient-color-picker": "^2.2.22",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react": "^4.0.3",
"autoprefixer": "^10.4.15",
"eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.29",
"tailwindcss": "^3.3.3",
"typescript": "^5.0.2",
"vite": "^4.4.5"
}
}
+11 -42
View File
@@ -1,51 +1,18 @@
// App.tsx import React from 'react';
import { useState } from 'react';
import TabbedContainer from './components/TabbedContainer'; import TabbedContainer from './components/TabbedContainer';
import Settings from './pages/Settings'; import Settings from './pages/Settings';
import logo from './assets/betterseqta-dark-full.png'; import logo from './assets/betterseqta-dark-full.png';
import logoDark from './assets/betterseqta-light-full.png'; import logoDark from './assets/betterseqta-light-full.png';
import Shortcuts from './pages/Shortcuts'; import Shortcuts from './pages/Shortcuts';
import About from './pages/About'; import About from './pages/About';
import { SettingsContextProvider } from './SettingsContext';
export interface SettingsState {
notificationCollector: boolean;
lessonAlerts: boolean;
animatedBackground: boolean;
animatedBackgroundSpeed: boolean;
customThemeColor: string;
betterSEQTAPlus: boolean;
}
const App: React.FC = () => { const App: React.FC = () => {
const [settingsState, setSettingsState] = useState<SettingsState>({
notificationCollector: false,
lessonAlerts: false,
animatedBackground: false,
animatedBackgroundSpeed: false,
customThemeColor: "#db6969",
betterSEQTAPlus: true
});
// Handler for Switches
const switchChange = (key: string, isOn: boolean) => {
setSettingsState({
...settingsState,
[key]: isOn,
});
};
// Handler for ColorPicker
const colorChange = (color: string) => {
setSettingsState({
...settingsState,
customThemeColor: color,
});
};
const tabs = [ const tabs = [
{ {
title: 'Settings', title: 'Settings',
content: <Settings settingsState={settingsState} switchChange={switchChange} colorChange={colorChange} /> content: <Settings />
}, },
{ {
title: 'Shortcuts', title: 'Shortcuts',
@@ -59,13 +26,15 @@ const App: React.FC = () => {
{/* <div className="flex justify-center w-screen h-screen pt-4 overflow-hidden" style={{ background: settingsState.customThemeColor }}> */} {/* <div className="flex justify-center w-screen h-screen pt-4 overflow-hidden" style={{ background: settingsState.customThemeColor }}> */}
return ( return (
<div className="flex flex-col w-[24rem] shadow-2xl gap-2 bg-white rounded-xl h-[590px] dark:bg-zinc-800 dark:text-white"> <SettingsContextProvider>
<div className="grid border-b border-b-zinc-200/40 place-items-center"> <div className="flex flex-col w-[384px] shadow-2xl gap-2 bg-white rounded-xl h-[590px] dark:bg-zinc-800 dark:text-white">
<img src={logo} className="w-4/5 dark:hidden" /> <div className="grid border-b border-b-zinc-200/40 place-items-center">
<img src={logoDark} className="hidden w-4/5 dark:block" /> <img src={logo} className="w-4/5 dark:hidden" />
<img src={logoDark} className="hidden w-4/5 dark:block" />
</div>
<TabbedContainer tabs={tabs} />
</div> </div>
<TabbedContainer themeColor={settingsState.customThemeColor} tabs={tabs} /> </SettingsContextProvider>
</div>
); );
}; };
+39
View File
@@ -0,0 +1,39 @@
// SettingsContext.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';
import { SettingsState } from './types/AppProps';
import useSettingsState from './hooks/settingsState';
// Create a context with an initial state
const SettingsContext = createContext<{
settingsState: SettingsState;
setSettingsState: React.Dispatch<React.SetStateAction<SettingsState>>;
} | undefined>(undefined);
export const SettingsContextProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [settingsState, setSettingsState] = useState<SettingsState>({
notificationCollector: false,
lessonAlerts: false,
animatedBackground: false,
animatedBackgroundSpeed: "0",
customThemeColor: "#db6969",
betterSEQTAPlus: true,
shortcuts: []
});
useSettingsState({ settingsState, setSettingsState });
return (
<SettingsContext.Provider value={{ settingsState, setSettingsState }}>
{children}
</SettingsContext.Provider>
);
};
// eslint-disable-next-line
export const useSettingsContext = () => {
const context = useContext(SettingsContext);
if (!context) {
throw new Error('useSettingsContext must be used within a SettingsContextProvider');
}
return context;
};
+8 -11
View File
@@ -1,12 +1,7 @@
// TODO: Create types for ColorPicker // @ts-expect-error There aren't any types for the below library
// @ts-expect-error No typescript declarations available
import ColorPicker from 'react-best-gradient-color-picker'; import ColorPicker from 'react-best-gradient-color-picker';
import { useState, useRef, useEffect } from 'react'; import { useState, useRef, useEffect } from 'react';
import type { ColorPickerProps } from '../types/ColorPickerProps';
interface ColorPickerProps {
color: string;
onChange: (color: string) => void;
}
const Picker = ({ color, onChange }: ColorPickerProps) => { const Picker = ({ color, onChange }: ColorPickerProps) => {
const [showPicker, setShowPicker] = useState<boolean>(false); const [showPicker, setShowPicker] = useState<boolean>(false);
@@ -27,18 +22,20 @@ const Picker = ({ color, onChange }: ColorPickerProps) => {
}, [showPicker]); }, [showPicker]);
return ( return (
<div className=""> <>
<button <button
onClick={() => setShowPicker(!showPicker)} onClick={() => setShowPicker(!showPicker)}
style={{ background: color }} style={{ background: color }}
className="w-16 h-8 rounded-md" className="w-16 h-8 rounded-md"
></button> ></button>
{showPicker && ( {showPicker && (
<div ref={ref} className="fixed top-0 left-0 z-50 p-4 bg-white border rounded-lg shadow-lg border-zinc-00"> <div className="absolute top-0 left-0 w-full h-full bg-black/20">
<ColorPicker value={color} onChange={onChange} /> <div ref={ref} className="fixed top-0 left-0 z-50 p-4 bg-white border rounded-lg shadow-lg border-zinc-00">
<ColorPicker value={color} onChange={onChange} />
</div>
</div> </div>
)} )}
</div> </>
); );
}; };
+1 -4
View File
@@ -1,9 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import "./Slider.css"; import "./Slider.css";
import type { Slider } from '../types/SliderProps';
interface Slider {
onValueChange: (value: number) => void;
}
const Slider: React.FC<Slider> = ({ onValueChange }) => { const Slider: React.FC<Slider> = ({ onValueChange }) => {
const [sliderValue, setSliderValue] = useState(0); const [sliderValue, setSliderValue] = useState(0);
+1
View File
@@ -1,3 +1,4 @@
.dark .switch[data-ison="true"],
.switch[data-ison="true"] { .switch[data-ison="true"] {
background-color: #30D259; background-color: #30D259;
} }
+1 -5
View File
@@ -1,10 +1,6 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import "./Switch.css"; import "./Switch.css";
import type { SwitchProps } from "../types/SwitchProps";
interface SwitchProps {
onChange: (isOn: boolean) => void;
state: boolean;
}
export default function Switch(props: SwitchProps) { export default function Switch(props: SwitchProps) {
const toggleSwitch = () => { const toggleSwitch = () => {
+53 -44
View File
@@ -1,22 +1,15 @@
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import { motion } from 'framer-motion'; import { motion, AnimatePresence } from 'framer-motion';
import type { TabbedContainerProps } from '../types/TabbedContainerProps';
import { useSettingsContext } from '../SettingsContext';
interface Tab { const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs }) => {
title: string;
content: JSX.Element;
}
interface TabbedContainerProps {
tabs: Tab[];
themeColor: string;
}
const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs, themeColor }) => {
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);
const [hoveredTab, setHoveredTab] = useState<number | null>(null); const [hoveredTab, setHoveredTab] = useState<number | null>(null);
const [tabWidth, setTabWidth] = useState(0); const [tabWidth, setTabWidth] = useState(0);
const [position, setPosition] = useState(0); const [position, setPosition] = useState(0);
const positionRef = useRef(position); const positionRef = useRef(position);
const themeColor = useSettingsContext().settingsState.customThemeColor;
useEffect(() => { useEffect(() => {
const newPosition = -activeTab * 100; const newPosition = -activeTab * 100;
@@ -28,6 +21,13 @@ const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs, themeColor }) =
const springTransition = { type: 'spring', stiffness: 250, damping: 25 }; const springTransition = { type: 'spring', stiffness: 250, damping: 25 };
const contentVariants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
};
const fastOpacityTransition = { duration: 0.2 };
useEffect(() => { useEffect(() => {
if (containerRef.current) { if (containerRef.current) {
// @ts-expect-error for some reason its giving an error in TS but it works... // @ts-expect-error for some reason its giving an error in TS but it works...
@@ -44,48 +44,57 @@ const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs, themeColor }) =
}; };
return ( return (
<div className="h-full px-4 overflow-y-scroll overflow-x-clip"> <>
<div ref={containerRef} className="sticky top-0 z-10 text-[0.875rem] mb-2 pb-2 bg-white"> <div ref={containerRef} className="top-0 z-10 text-[0.875rem] mb-2 pb-2 mx-4">
<div className="relative flex"> <div className="relative flex">
<motion.div <motion.div
className="absolute top-0 left-0 z-0 h-full rounded-full opacity-40" className="absolute top-0 left-0 z-0 h-full rounded-full opacity-40"
style={{ width: `${tabWidth}px`, background: themeColor }} style={{ width: `${tabWidth}px`, background: themeColor }}
initial={false} initial={false}
animate={{ x: calcXPos(hoveredTab) }} animate={{ x: calcXPos(hoveredTab) }}
transition={springTransition} transition={springTransition}
/> />
{tabs.map((tab, index) => ( {tabs.map((tab, index) => (
<button <button
key={index} key={index}
className="relative z-10 flex-1 px-4 py-2" className="relative z-10 flex-1 px-4 py-2"
onClick={() => setActiveTab(index)} onClick={() => setActiveTab(index)}
onMouseEnter={() => setHoveredTab(index)} onMouseEnter={() => setHoveredTab(index)}
onMouseLeave={() => setHoveredTab(null)} onMouseLeave={() => setHoveredTab(null)}
> >
{tab.title} {tab.title}
</button> </button>
))} ))}
</div>
</div> </div>
<div className="relative"> </div>
<div className="h-full px-4 overflow-y-scroll overflow-x-clip">
<motion.div <motion.div
initial={false} initial={false}
animate={{ x: `${position}%` }} animate={{ x: `${position}%` }}
transition={springTransition} transition={springTransition}
> >
<div className="absolute flex w-full" style={{ left: `${-position}%` }}> <div className="absolute flex w-full" style={{ left: `${-position}%` }}>
{tabs.map((tab, index) => ( <AnimatePresence>
<div {tabs.map((tab, index) => (
key={index} activeTab === index && (
className={`w-full ${activeTab === index ? '' : 'hidden'}`} <motion.div
> key={index}
{tab.content} className="absolute w-full"
</div> initial="hidden"
))} animate="visible"
exit="hidden"
transition={fastOpacityTransition}
variants={contentVariants}
>
{tab.content}
</motion.div>
)
))}
</AnimatePresence>
</div> </div>
</motion.div> </motion.div>
</div> </div>
</div> </>
); );
}; };
+94
View File
@@ -0,0 +1,94 @@
/*global chrome*/
import { useEffect, useMemo } from "react";
import { SettingsProps } from "../types/SettingsProps";
import { MainConfig, SettingsState } from "../types/AppProps";
let RanOnce = false;
let previousSettingsState: SettingsState
const useSettingsState = ({ settingsState, setSettingsState }: SettingsProps) => {
useEffect(() => {
if (RanOnce) return;
RanOnce = true;
// get the current settings state
chrome.storage.local.get(function(result: MainConfig) {
console.log(result);
setSettingsState({
notificationCollector: result.notificationcollector,
lessonAlerts: result.lessonalert,
animatedBackground: result.animatedbk,
animatedBackgroundSpeed: result.bksliderinput,
customThemeColor: result.selectedColor,
betterSEQTAPlus: result.onoff,
shortcuts: result.shortcuts,
customshortcuts: result.customshortcuts,
});
if (result.DarkMode) {
document.body.classList.add('dark');
}
});
});
const keyToStateMap = useMemo(() => ({
"notificationcollector": "notificationCollector",
"lessonalert": "lessonAlerts",
"animatedbk": "animatedBackground",
"bksliderinput": "animatedBackgroundSpeed",
"selectedColor": "customThemeColor",
"onoff": "betterSEQTAPlus",
"shortcuts": "shortcuts",
"customshortcuts": "customshortcuts",
}), []);
const storageChangeListener = (changes: chrome.storage.StorageChange) => {
console.log(settingsState);
for (const [key, { newValue }] of Object.entries(changes)) {
if (key === "DarkMode") {
if (key === "DarkMode" && newValue) {
document.body.classList.add('dark');
} else {
document.body.classList.remove('dark');
}
}
// @ts-expect-error - TODO: Fix this
const stateKey = keyToStateMap[key as keyof MainConfig];
if (stateKey) {
setSettingsState((prevState: SettingsState) => ({
...prevState,
[stateKey]: newValue
}));
}
}
};
useEffect(() => {
chrome.storage.onChanged.addListener(storageChangeListener);
return () => {
chrome.storage.onChanged.removeListener(storageChangeListener);
};
});
const setStorage = (key: keyof MainConfig, value: any) => {
chrome.storage.local.set({ [key]: value });
}
useEffect(() => {
if (previousSettingsState) {
for (const [key, value] of Object.entries(settingsState)) {
// @ts-expect-error - TODO: Fix this
const storageKey = Object.keys(keyToStateMap).find(k => keyToStateMap[k] === key);
// @ts-expect-error - TODO: Fix this
if (storageKey && value !== previousSettingsState[key]) {
setStorage(storageKey as keyof MainConfig, value);
}
}
}
previousSettingsState = settingsState;
}, [settingsState, keyToStateMap])
}
export default useSettingsState;
+6
View File
@@ -0,0 +1,6 @@
import './index.css';
declare module "*.png";
declare module "*.svg";
declare module "*.jpeg";
declare module "*.jpg";
+2 -2
View File
@@ -1,6 +1,6 @@
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App' import App from './App.js'
import './index.css' import './index.css'
const root = ReactDOM.createRoot(document.getElementById('ExtensionPopup')!); const root = ReactDOM.createRoot(document.getElementById('ExtensionPopup')!);
@@ -9,4 +9,4 @@ root.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />
</React.StrictMode>, </React.StrictMode>,
) );
+21 -16
View File
@@ -1,21 +1,26 @@
import Switch from '../components/Switch'; import Switch from '../components/Switch';
import ColorPicker from '../components/ColorPicker'; import ColorPicker from '../components/ColorPicker';
import { SettingsState } from '../App'; import { SettingsList } from '../types/SettingsProps';
import { useSettingsContext } from '../SettingsContext';
interface ISetting { const Settings: React.FC = () => {
title: string; const { settingsState, setSettingsState } = useSettingsContext();
description: string;
modifyElement: JSX.Element;
}
interface SettingsProps { const switchChange = (key: string, isOn: boolean) => {
settingsState: SettingsState; setSettingsState({
switchChange: (key: string, isOn: boolean) => void; ...settingsState,
colorChange: (color: string) => void; [key]: isOn,
} });
};
const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorChange }) => { const colorChange = (color: string) => {
const settings: ISetting[] = [ setSettingsState({
...settingsState,
customThemeColor: color,
});
};
const settings: SettingsList[] = [
{ {
title: "Notification Collector", title: "Notification Collector",
description: "Uncaps the 9+ limit for notifications, showing the real number.", description: "Uncaps the 9+ limit for notifications, showing the real number.",
@@ -34,7 +39,7 @@ const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorC
{ {
title: "Animated Background Speed", title: "Animated Background Speed",
description: "Controls the speed of the animated background.", description: "Controls the speed of the animated background.",
modifyElement: <Switch state={settingsState.animatedBackgroundSpeed} onChange={(isOn: boolean) => switchChange('animatedBackgroundSpeed', isOn)} /> modifyElement: <div>Insert Slider Please</div>
}, },
{ {
title: "Custom Theme Colour", title: "Custom Theme Colour",
@@ -43,13 +48,13 @@ const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorC
}, },
{ {
title: "BetterSEQTA+", title: "BetterSEQTA+",
description: "Unlocks premium features.", description: "Enables BetterSEQTA+ features",
modifyElement: <Switch state={settingsState.betterSEQTAPlus} onChange={(isOn: boolean) => switchChange('betterSEQTAPlus', isOn)} /> modifyElement: <Switch state={settingsState.betterSEQTAPlus} onChange={(isOn: boolean) => switchChange('betterSEQTAPlus', isOn)} />
} }
]; ];
return ( return (
<div className="flex flex-col overflow-y-scroll divide-y divide-zinc-100"> <div className="flex flex-col -mt-4 overflow-y-scroll divide-y divide-zinc-100">
{settings.map((setting, index) => ( {settings.map((setting, index) => (
<div className="flex items-center justify-between px-4 py-3" key={index}> <div className="flex items-center justify-between px-4 py-3" key={index}>
<div className="pr-4"> <div className="pr-4">
+143 -80
View File
@@ -1,95 +1,158 @@
import { useState } from "react"; import { useState } from "react";
import Switch from "../components/Switch"; import Switch from "../components/Switch";
import { useSettingsContext } from "../SettingsContext";
import { motion, AnimatePresence } from "framer-motion";
interface Shortcut {
name: string;
url: string;
enabled?: boolean;
}
export default function Shortcuts() { export default function Shortcuts() {
const [shortcutState, setShortcutState] = useState({ const { settingsState, setSettingsState } = useSettingsContext();
youtube: false,
outlook: false,
office: false,
spotify: false,
google: false,
duckduckgo: false,
coolmathgames: false,
sace: false,
googlescholar: false,
gmail: false,
netflix: false
});
// Handler for Switches const switchChange = (shortcutName: string, isOn: boolean): void => {
const switchChange = (key: string, isOn: boolean) => { const updatedShortcuts = settingsState.shortcuts.map((shortcut) => {
setShortcutState({ if (shortcut.name === shortcutName) {
...shortcutState, return { ...shortcut, enabled: isOn };
[key]: isOn, }
return shortcut;
}); });
setSettingsState({ ...settingsState, shortcuts: updatedShortcuts });
}; };
const DefaultShortcuts = [ const [newTitle, setNewTitle] = useState<string>("");
{ const [newURL, setNewURL] = useState<string>("");
title: "YouTube",
link: "https://youtube.com", const isValidTitle = (title: string): boolean => title.trim() !== "";
modifyElement: <Switch state={shortcutState.youtube} onChange={(isOn: boolean) => switchChange('youtube', isOn)} />
}, const isValidURL = (url: string): boolean => {
{ const pattern = new RegExp("^(https?:\\/\\/)?[\\w.-]+[\\w.-]+$", "i");
title: "Outlook", return pattern.test(url);
link: "https://outlook.office.com/mail/inbox", };
modifyElement: <Switch state={shortcutState.outlook} onChange={(isOn: boolean) => switchChange('outlook', isOn)} />
}, const addNewCustomShortcut = (): void => {
{ if (isValidTitle(newTitle) && isValidURL(newURL)) {
title: "Office", const newShortcut: Shortcut = { name: newTitle.trim(), url: newURL.trim() };
link: "https://www.office.com/", const updatedCustomShortcuts = [...settingsState.customshortcuts, newShortcut];
modifyElement: <Switch state={shortcutState.office} onChange={(isOn: boolean) => switchChange('office', isOn)} /> setSettingsState({ ...settingsState, customshortcuts: updatedCustomShortcuts });
}, setNewTitle("");
{ setNewURL("");
title: "Spotify",
link: "https://www.spotify.com/", setFormVisible(false);
modifyElement: <Switch state={shortcutState.spotify} onChange={(isOn: boolean) => switchChange('spotify', isOn)} /> } else {
}, // Replace with a more user-friendly way to display errors
{ console.error("Please enter a valid title and URL.");
title: "Google",
link: "https://www.google.com/",
modifyElement: <Switch state={shortcutState.google} onChange={(isOn: boolean) => switchChange('google', isOn)} />
},
{
title: "DuckDuckGo",
link: "https://duckduckgo.com/",
modifyElement: <Switch state={shortcutState.duckduckgo} onChange={(isOn: boolean) => switchChange('duckduckgo', isOn)} />
},
{
title: "Cool Math Games",
link: "https://www.coolmathgames.com/",
modifyElement: <Switch state={shortcutState.coolmathgames} onChange={(isOn: boolean) => switchChange('coolmathgames', isOn)} />
},
{
title: "SACE",
link: "https://www.sace.sa.edu.au/",
modifyElement: <Switch state={shortcutState.sace} onChange={(isOn: boolean) => switchChange('sace', isOn)} />
},
{
title: "Google Scholar",
link: "https://scholar.google.com/",
modifyElement: <Switch state={shortcutState.googlescholar} onChange={(isOn: boolean) => switchChange('googlescholar', isOn)} />
},
{
title: "Gmail",
link: "https://mail.google.com/",
modifyElement: <Switch state={shortcutState.gmail} onChange={(isOn: boolean) => switchChange('gmail', isOn)} />
},
{
title: "Netflix",
link: "https://www.netflix.com/",
modifyElement: <Switch state={shortcutState.netflix} onChange={(isOn: boolean) => switchChange('netflix', isOn)} />
} }
]; };
const deleteCustomShortcut = (index: number): void => {
const updatedCustomShortcuts = settingsState.customshortcuts.filter((_, i) => i !== index);
setSettingsState({ ...settingsState, customshortcuts: updatedCustomShortcuts });
};
const [isFormVisible, setFormVisible] = useState(false);
const toggleForm = () => {
setFormVisible(!isFormVisible);
};
return ( return (
<div className="flex flex-col divide-y divide-zinc-100"> <div className="flex flex-col divide-y divide-zinc-100">
{DefaultShortcuts.map((shortcut, index) => (
<div className="flex items-center justify-between px-4 py-3" key={index}> <AnimatePresence>
{shortcut.title} {isFormVisible ? (
{shortcut.modifyElement} <motion.div
</div> initial={{ opacity: 0, height: 0 }}
))} animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ type: "spring", damping: 20 }}
>
<div className="flex flex-col items-center mb-4">
<motion.input
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="w-full p-2 rounded-md bg-zinc-100 dark:bg-zinc-700 focus:outline-none"
type="text"
placeholder="Shortcut Name"
value={newTitle}
onChange={(e) => setNewTitle(e.target.value)}
/>
<motion.input
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="w-full p-2 my-2 rounded-md bg-zinc-100 dark:bg-zinc-700 focus:outline-none"
type="text"
placeholder="URL eg. https://google.com"
value={newURL}
onChange={(e) => setNewURL(e.target.value)}
/>
<motion.button
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
className="w-full px-4 py-2 text-white bg-blue-500 rounded-md"
onClick={ addNewCustomShortcut }
>
Add
</motion.button>
</div>
</motion.div>
) : (
<motion.button
initial={{ backgroundColor: "rgba(29, 161, 242, 1)", height: "auto" }}
animate={{ backgroundColor: "rgba(29, 161, 242, 1)", height: "auto" }}
exit={{ backgroundColor: "rgba(29, 161, 242, 1)", height: "auto" }}
transition={{ type: 'tween', ease: "easeOut" }}
className="px-4 py-2 mb-4 text-white bg-blue-500 rounded"
onClick={toggleForm}
>
Add Custom Shortcut
</motion.button>
)}
</AnimatePresence>
{/* Shortcuts Section */}
{settingsState.shortcuts ? (
settingsState.shortcuts.map((shortcut) => shortcut.name && (
<div className="flex items-center justify-between px-4 py-3" key={shortcut.name}>
{shortcut.name}
<Switch state={shortcut.enabled} onChange={(isOn) => switchChange(shortcut.name, isOn)} />
</div>
))
) : (
<p>Loading shortcuts...</p>
)}
{/* Custom Shortcuts Section */}
{settingsState.customshortcuts ? (
settingsState.customshortcuts.map((shortcut, index) => (
<div className="flex items-center justify-between px-4 py-3" key={shortcut.name}>
{shortcut.name}
<button onClick={() => deleteCustomShortcut(index)}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="w-4 h-4 text-red-500"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
// eslint-disable-next-line max-len
d="M15.707 4.293a1 1 0 010 1.414L11.414 10l4.293 4.293a1 1 0 11-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 11-1.414-1.414L8.586 10 4.293 5.707a1 1 0 111.414-1.414L10 8.586l4.293-4.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
))
) : (
<p>Loading custom shortcuts...</p>
)}
</div> </div>
); );
} }
+57
View File
@@ -0,0 +1,57 @@
export interface SettingsState {
notificationCollector: boolean;
lessonAlerts: boolean;
animatedBackground: boolean;
animatedBackgroundSpeed: string;
customThemeColor: string;
betterSEQTAPlus: boolean;
shortcuts: Shortcut[];
customshortcuts: CustomShortcut[];
}
interface ToggleItem {
toggle: boolean;
}
interface Shortcut {
enabled: boolean;
name: string;
}
interface CustomShortcut {
name: string;
url: string;
}
export interface MainConfig {
DarkMode: boolean;
animatedbk: boolean;
bksliderinput: string;
customshortcuts: CustomShortcut[];
defaultmenuorder: any[];
lessonalert: boolean;
menuitems: {
assessments: ToggleItem;
courses: ToggleItem;
dashboard: ToggleItem;
documents: ToggleItem;
forums: ToggleItem;
goals: ToggleItem;
home: ToggleItem;
messages: ToggleItem;
myed: ToggleItem;
news: ToggleItem;
notices: ToggleItem;
portals: ToggleItem;
reports: ToggleItem;
settings: ToggleItem;
timetable: ToggleItem;
welcome: ToggleItem;
};
menuorder: any[];
notificationcollector: boolean;
onoff: boolean;
selectedColor: string;
shortcuts: Shortcut[];
subjectfilters: Record<string, any>;
}
+4
View File
@@ -0,0 +1,4 @@
export interface ColorPickerProps {
color: string;
onChange: (color: string) => void;
}
+11
View File
@@ -0,0 +1,11 @@
import type { SettingsState } from './AppProps';
export interface SettingsList {
title: string;
description: string;
modifyElement: JSX.Element;
}
export interface SettingsProps {
settingsState: SettingsState;
setSettingsState: React.Dispatch<React.SetStateAction<SettingsState>>;
}
+7
View File
@@ -0,0 +1,7 @@
import React from 'react';
import "./Slider.css";
export interface Slider {
onValueChange: (value: number) => void;
}
declare const Slider: React.FC<Slider>;
export default Slider;
+6
View File
@@ -0,0 +1,6 @@
import "./Switch.css";
export interface SwitchProps {
onChange: (isOn: boolean) => void;
state: boolean;
}
@@ -0,0 +1,10 @@
import React, { JSX } from 'react';
export interface Tab {
title: string;
content: JSX.Element;
}
export interface TabbedContainerProps {
tabs: Tab[];
}
declare const TabbedContainer: React.FC<TabbedContainerProps>;
export default TabbedContainer;
+24
View File
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
+2
View File
@@ -0,0 +1,2 @@
declare const _default: import("vite").UserConfig;
export default _default;
+17
View File
@@ -0,0 +1,17 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
build: {
//outDir: '../../public/popup-dist',
rollupOptions: {
output: {
assetFileNames: 'client/rsc/[ext]/[name][extname]',
chunkFileNames: 'client/rsc/[chunks]/[name].[hash].js',
entryFileNames: 'client/public/client.js'
}
}
}
})
+12
View File
@@ -27,5 +27,17 @@
"webextension-polyfill": "^0.10.0", "webextension-polyfill": "^0.10.0",
"webpack": "^5.88.2", "webpack": "^5.88.2",
"webpack-cli": "^5.1.4" "webpack-cli": "^5.1.4"
},
"dependencies": {
"@types/color": "^3.0.4",
"@types/react": "^18.2.21",
"autoprefixer": "^10.4.15",
"color": "^4.2.3",
"install": "^0.13.0",
"npm": "^10.1.0",
"postcss": "^8.4.29",
"react": "^18.2.0",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2"
} }
} }
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: [
require("tailwindcss"),
require("autoprefixer"),
],
};
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: [
require("tailwindcss"),
require("autoprefixer"),
],
};
+16
View File
@@ -50,6 +50,22 @@
{ {
"resources": ["popup/*"], "resources": ["popup/*"],
"matches": ["*://*/*"] "matches": ["*://*/*"]
},
{
"resources": ["client.js"],
"matches": ["*://*/*"]
},
{
"resources": ["index.css"],
"matches": ["*://*/*"]
},
{
"resources": ["interface/*"],
"matches": ["*://*/*"]
},
{
"resources": ["client/*"],
"matches": ["*://*/*"]
} }
] ]
} }
+1 -2
View File
@@ -14,13 +14,12 @@
@import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,600"); @import url("https://fonts.googleapis.com/css?family=Rubik:300,400,500,600");
.outside-container { .outside-container {
width: 350px;
margin: 0; margin: 0;
background-color: #131313;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
right: 10px; right: 10px;
top: 80px; top: 80px;
height: 590px;
z-index: 20; z-index: 20;
} }
+183 -133
View File
@@ -1,4 +1,6 @@
/*global chrome*/ /*global chrome*/
import Color from "color";
import ShortcutLinks from "./seqta/content/links.json"; import ShortcutLinks from "./seqta/content/links.json";
import MenuitemSVGKey from "./seqta/content/MenuItemSVGKey.json"; import MenuitemSVGKey from "./seqta/content/MenuItemSVGKey.json";
import stringToHTML from "./seqta/utils/stringToHTML.js"; import stringToHTML from "./seqta/utils/stringToHTML.js";
@@ -13,7 +15,6 @@ let SettingsClicked = false;
let MenuOptionsOpen = false; let MenuOptionsOpen = false;
let UserInitalCode = ""; let UserInitalCode = "";
let currentSelectedDate = new Date(); let currentSelectedDate = new Date();
let WhatsNewOpen = false;
let LessonInterval; let LessonInterval;
let DarkMode; let DarkMode;
@@ -25,7 +26,7 @@ function SetDisplayNone(ElementName) {
return `li[data-key=${ElementName}]{display:var(--menuHidden) !important; transition: 1s;}`; return `li[data-key=${ElementName}]{display:var(--menuHidden) !important; transition: 1s;}`;
} }
function animbkEnable (item) { function animbkEnable(item) {
if (item.animatedbk) { if (item.animatedbk) {
CreateBackground(); CreateBackground();
} else { } else {
@@ -38,7 +39,9 @@ function bkValues (item) {
const bg = document.getElementsByClassName("bg"); const bg = document.getElementsByClassName("bg");
const bg2 = document.getElementsByClassName("bg2"); const bg2 = document.getElementsByClassName("bg2");
const bg3 = document.getElementsByClassName("bg3"); const bg3 = document.getElementsByClassName("bg3");
const value = 200 - item.bksliderinput; const value = 200 - item.bksliderinput; // reverse the slider direction to match the animation direction
if (bg.length == 0 || bg2.length == 0 || bg3.length == 0) return;
const minDuration = 1; // minimum duration in seconds const minDuration = 1; // minimum duration in seconds
const maxDuration = 10; // maximum duration in seconds const maxDuration = 10; // maximum duration in seconds
@@ -172,12 +175,12 @@ function OpenWhatsNewPopup() {
var bkelement = document.getElementById("whatsnewbk"); var bkelement = document.getElementById("whatsnewbk");
bkelement.addEventListener("click", function () { bkelement.addEventListener("click", function () {
DeleteWhatsNew(); DeleteWhatsNew();
WhatsNewOpen = false; //WhatsNewOpen = false;
}); });
var closeelement = document.getElementById("whatsnewclosebutton"); var closeelement = document.getElementById("whatsnewclosebutton");
closeelement.addEventListener("click", function () { closeelement.addEventListener("click", function () {
DeleteWhatsNew(); DeleteWhatsNew();
WhatsNewOpen = false; //WhatsNewOpen = false;
}); });
} }
@@ -193,7 +196,7 @@ async function finishLoad() {
chrome.storage.local.get(["justupdated"], function (result) { chrome.storage.local.get(["justupdated"], function (result) {
if (result.justupdated) { if (result.justupdated) {
WhatsNewOpen = true; //WhatsNewOpen = true;
OpenWhatsNewPopup(); OpenWhatsNewPopup();
} }
}); });
@@ -233,6 +236,9 @@ function RemoveBackground() {
var bk = document.getElementsByClassName("bg"); var bk = document.getElementsByClassName("bg");
var bk2 = document.getElementsByClassName("bg2"); var bk2 = document.getElementsByClassName("bg2");
var bk3 = document.getElementsByClassName("bg3"); var bk3 = document.getElementsByClassName("bg3");
if (bk.length == 0 || bk2.length == 0 || bk3.length == 0) return;
bk[0].remove(); bk[0].remove();
bk2[0].remove(); bk2[0].remove();
bk3[0].remove(); bk3[0].remove();
@@ -621,116 +627,116 @@ function AppendElementsToDisabledPage() {
document.head.append(settingsStyle); document.head.append(settingsStyle);
} }
function lightenAndPaleColor( function lightenAndPaleColor(inputColor, lightenFactor = 0.75, paleFactor = 0.55) {
hexColor, // Step 1: Convert RGBA to separate R, G and B values
lightenFactor = 0.75, const [r, g, b] = inputColor.match(/\d+/g).map(Number);
paleFactor = 0.55,
) { // Step 2: Convert RGB to HSL
// Convert a RGB value to HSL let r1 = r / 255, g1 = g / 255, b1 = b / 255;
function rgbToHsl(r, g, b) { const max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1);
(r /= 255), (g /= 255), (b /= 255); let h, s, l = (max + min) / 2;
let max = Math.max(r, g, b),
min = Math.min(r, g, b); if (max === min) {
let h, h = s = 0;
s, } else {
l = (max + min) / 2; const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r1: h = (g1 - b1) / d + (g1 < b1 ? 6 : 0); break;
case g1: h = (b1 - r1) / d + 2; break;
case b1: h = (r1 - g1) / d + 4; break;
if (max === min) {
h = s = 0;
} else {
let d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
} }
h /= 6;
return [h, s, l];
} }
// Convert an HSL value to RGB // Step 3: Adjust saturation and lightness
function hslToRgb(h, s, l) {
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
let p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [r * 255, g * 255, b * 255];
}
// Extract the red, green, and blue components from hex
let r = parseInt(hexColor.substr(1, 2), 16);
let g = parseInt(hexColor.substr(3, 2), 16);
let b = parseInt(hexColor.substr(5, 2), 16);
// Convert RGB to HSL
let [h, s, l] = rgbToHsl(r, g, b);
// Adjust saturation and lightness
s -= s * paleFactor; s -= s * paleFactor;
l += (1 - l) * lightenFactor; l += (1 - l) * lightenFactor;
// Convert HSL back to RGB // Step 4: Convert HSL back to RGB
[r, g, b] = hslToRgb(h, s, l); const hue2rgb = (p, q, t) => {
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
// Convert RGB to hex let r2, g2, b2;
r = Math.round(r).toString(16).padStart(2, "0"); if (s === 0) {
g = Math.round(g).toString(16).padStart(2, "0"); r2 = g2 = b2 = l;
b = Math.round(b).toString(16).padStart(2, "0"); } else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
return "#" + r + g + b; const p = 2 * l - q;
} r2 = hue2rgb(p, q, h + 1/3);
g2 = hue2rgb(p, q, h);
function ColorLuminance(hex, lum) { b2 = hue2rgb(p, q, h - 1/3);
// validate hex string
hex = String(hex).replace(/[^0-9a-f]/gi, "");
if (hex.length < 6) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
lum = lum || 0;
// convert to decimal and change luminosity
var rgb = "#",
c,
i;
for (i = 0; i < 3; i++) {
c = parseInt(hex.substr(i * 2, 2), 16);
c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
rgb += ("00" + c).substring(c.length);
} }
return rgb; // Step 5: Format Output
const result = `rgb(${Math.round(r2 * 255)}, ${Math.round(g2 * 255)}, ${Math.round(b2 * 255)})`;
return `${result}`;
} }
function ColorLuminance(color, lum = 0) {
// Regular expression to match RGBA colors
const rgbaRegex = /rgba?\(([^)]+)\)/g;
// Check if the input color is a gradient (linear or radial)
if (color.includes("gradient")) {
let gradient = color;
// Find and replace all instances of RGBA in the gradient
let match;
while ((match = rgbaRegex.exec(color)) !== null) {
const rgbaString = match[1];
const [r, g, b, a] = rgbaString.split(",").map(str => str.trim());
// Apply the original luminance adjustment logic
let adjustedRgba = [];
for (let c of [r, g, b]) {
c = Math.round(Math.min(Math.max(0, c + c * lum), 255));
adjustedRgba.push(c);
}
adjustedRgba.push(a); // Add the alpha component back
// Replace the original RGBA string with the adjusted one
gradient = gradient.replace(`rgba(${rgbaString})`, `rgba(${adjustedRgba.join(", ")})`);
}
return gradient;
} else {
// Handle as a simple color (could be HEX, RGBA, etc., as supported by your Color library)
const hexColor = Color(color).hex();
let adjustedHex = String(hexColor).replace(/[^0-9a-f]/gi, "");
if (adjustedHex.length < 6) {
adjustedHex = adjustedHex[0] + adjustedHex[0] + adjustedHex[1] + adjustedHex[1] + adjustedHex[2] + adjustedHex[2];
}
let rgb = "#",
c;
for (let i = 0; i < 3; i++) {
c = parseInt(adjustedHex.substr(i * 2, 2), 16);
c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16);
rgb += ("00" + c).substring(c.length);
}
return Color(rgb).hex();
}
}
chrome.storage.onChanged.addListener(function (changes) { chrome.storage.onChanged.addListener(function (changes) {
if (changes.selectedColor) { if (changes.selectedColor) {
try { try {
chrome.storage.local.get(["DarkMode"], function (result) { chrome.storage.local.get(["DarkMode"], function (result) {
if (!result.DarkMode) { if (!result.DarkMode) {
console.log(changes.selectedColor.newValue);
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
"--better-pale", "--better-pale",
lightenAndPaleColor(changes.selectedColor.newValue), lightenAndPaleColor(changes.selectedColor.newValue),
@@ -742,6 +748,7 @@ chrome.storage.onChanged.addListener(function (changes) {
} }
let rbg = GetThresholdofHex(changes.selectedColor.newValue); let rbg = GetThresholdofHex(changes.selectedColor.newValue);
if (rbg > 210) { if (rbg > 210) {
document.documentElement.style.setProperty("--text-color", "black"); document.documentElement.style.setProperty("--text-color", "black");
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
@@ -760,7 +767,6 @@ chrome.storage.onChanged.addListener(function (changes) {
"--better-main", "--better-main",
changes.selectedColor.newValue, changes.selectedColor.newValue,
); );
// document.documentElement.style.setProperty('--better-sub', ColorLuminance(changes.selectedColor.newValue, -0.15));
if (changes.selectedColor.newValue == "#ffffff") { if (changes.selectedColor.newValue == "#ffffff") {
document.documentElement.style.setProperty("--better-light", "#b7b7b7"); document.documentElement.style.setProperty("--better-light", "#b7b7b7");
@@ -801,7 +807,7 @@ async function CheckLoadOnPeriods() {
} }
} }
function RunFunctionOnTrue(storedSetting) { function main(storedSetting) {
DarkMode = storedSetting.DarkMode; DarkMode = storedSetting.DarkMode;
// If the option is 'on', open BetterSEQTA // If the option is 'on', open BetterSEQTA
if (typeof storedSetting.onoff == "undefined") { if (typeof storedSetting.onoff == "undefined") {
@@ -891,7 +897,6 @@ function RunFunctionOnTrue(storedSetting) {
"--better-main", "--better-main",
storedSetting.selectedColor, storedSetting.selectedColor,
); );
// document.documentElement.style.setProperty('--better-sub', ColorLuminance(storedSetting.selectedColor, -0.15));
if (storedSetting.selectedColor == "#ffffff") { if (storedSetting.selectedColor == "#ffffff") {
document.documentElement.style.setProperty("--better-light", "#b7b7b7"); document.documentElement.style.setProperty("--better-light", "#b7b7b7");
@@ -966,7 +971,7 @@ document.addEventListener(
document.getElementsByTagName("html")[0].appendChild(link); document.getElementsByTagName("html")[0].appendChild(link);
chrome.storage.local.get(null, function (items) { chrome.storage.local.get(null, function (items) {
RunFunctionOnTrue(items); main(items);
}); });
} }
if ( if (
@@ -978,7 +983,7 @@ document.addEventListener(
}, },
true, true,
); );
/*
function RunExtensionSettingsJS() { function RunExtensionSettingsJS() {
const whatsnewsettings = document.getElementById("whatsnewsettings"); const whatsnewsettings = document.getElementById("whatsnewsettings");
whatsnewsettings.addEventListener("click", function () { whatsnewsettings.addEventListener("click", function () {
@@ -1043,9 +1048,9 @@ function RunExtensionSettingsJS() {
function FindSEQTATab() { function FindSEQTATab() {
chrome.runtime.sendMessage({ type: "reloadTabs" }); chrome.runtime.sendMessage({ type: "reloadTabs" });
} }
/*
Store the currently selected settings using chrome.storage.local. // Store the currently selected settings using chrome.storage.local.
*/
function storeSettings() { function storeSettings() {
chrome.storage.local.set({ onoff: onoffselection.checked }, function () { chrome.storage.local.set({ onoff: onoffselection.checked }, function () {
FindSEQTATab(); FindSEQTATab();
@@ -1072,10 +1077,10 @@ function RunExtensionSettingsJS() {
FindSEQTATab(); FindSEQTATab();
} }
/*
Update the options UI with the settings values retrieved from storage, // Update the options UI with the settings values retrieved from storage,
or the default settings if the stored settings are empty. // or the default settings if the stored settings are empty.
*/
function updateUI(restoredSettings) { function updateUI(restoredSettings) {
if (typeof restoredSettings.onoff == "undefined") { if (typeof restoredSettings.onoff == "undefined") {
chrome.runtime.sendMessage({ type: "setDefaultStorage" }); chrome.runtime.sendMessage({ type: "setDefaultStorage" });
@@ -1310,7 +1315,7 @@ function RunExtensionSettingsJS() {
chrome.storage.local.set({ selectedColor: b }); chrome.storage.local.set({ selectedColor: b });
} }
}); });
} }*/
function CallExtensionSettings() { function CallExtensionSettings() {
// Injecting CSS File to the webpage to overwrite iFrame default CSS // Injecting CSS File to the webpage to overwrite iFrame default CSS
@@ -1333,7 +1338,7 @@ function CallExtensionSettings() {
fileref.setAttribute("href", cssFile); fileref.setAttribute("href", cssFile);
document.head.append(fileref); document.head.append(fileref);
let Settings = /*let Settings =
stringToHTML( stringToHTML(
String.raw` String.raw`
<div class="outside-container hidden" id="ExtensionPopup"><div class="logo-container"><img src=${chrome.runtime.getURL( <div class="outside-container hidden" id="ExtensionPopup"><div class="logo-container"><img src=${chrome.runtime.getURL(
@@ -1580,14 +1585,31 @@ function CallExtensionSettings() {
<p style="margin: 0; flex: 1; padding-left: 24px; margin-right: 5px; color: white;">By SethBurkart123</p> <p style="margin: 0; flex: 1; padding-left: 24px; margin-right: 5px; color: white;">By SethBurkart123</p>
<button style="margin: 0; margin-right: 20px; cursor:pointer; padding: 8px 10px; background: #ff5f5f; color:#1a1a1a;font-weight: 500; border-radius: 10px;" id="whatsnewsettings">Changelog v${chrome.runtime.getManifest().version}</button> <button style="margin: 0; margin-right: 20px; cursor:pointer; padding: 8px 10px; background: #ff5f5f; color:#1a1a1a;font-weight: 500; border-radius: 10px;" id="whatsnewsettings">Changelog v${chrome.runtime.getManifest().version}</button>
</div> </div>
</div></div>`); </div></div>`);*/
document.body.append(Settings.firstChild); let Settings2 =
stringToHTML(
String.raw`
<div class="outside-container hide" id="ExtensionPopup">
</div>
`);
document.body.append(Settings2.firstChild);
// add an iframe to the div: <iframe src="interface/index.html"></iframe>
let iframe = document.createElement("iframe");
iframe.src = chrome.runtime.getURL("interface/index.html");
iframe.allowTransparency = "true";
iframe.style.width = "384px";
iframe.style.height = "590px";
iframe.style.border = "none";
iframe.setAttribute("excludeDarkCheck", "true");
document.getElementById("ExtensionPopup").append(iframe);
var container = document.getElementById("container"); var container = document.getElementById("container");
var extensionsettings = document.getElementById("ExtensionPopup"); var extensionsettings = document.getElementById("ExtensionPopup");
container.onclick = function () { container.onclick = function () {
if (!SettingsClicked) { if (!SettingsClicked) {
extensionsettings.classList.add("hidden"); extensionsettings.classList.add("hide");
} }
SettingsClicked = false; SettingsClicked = false;
}; };
@@ -1981,10 +2003,12 @@ function AddBetterSEQTAElements(toggle) {
students[index]?.house_colour, students[index]?.house_colour,
); );
if (colorresult > 300) { if (colorresult && colorresult > 300) {
houseelement.style.color = "black"; houseelement.style.color = "black";
} else { } else if (colorresult < 300) {
houseelement.style.color = "white"; houseelement.style.color = "white";
} else {
houseelement.style.color = "black";
} }
houseelement.innerText = houseelement.innerText =
students[index].year + students[index].house; students[index].year + students[index].house;
@@ -2050,8 +2074,9 @@ function AddBetterSEQTAElements(toggle) {
} }
CallExtensionSettings(); CallExtensionSettings();
RunExtensionSettingsJS(); //RunExtensionSettingsJS();
// If betterSEQTA+ is enabled, run the code
if (toggle) { if (toggle) {
// Creates settings and dashboard buttons next to alerts // Creates settings and dashboard buttons next to alerts
var SettingsButton = stringToHTML( var SettingsButton = stringToHTML(
@@ -2112,6 +2137,11 @@ function AddBetterSEQTAElements(toggle) {
for (let i = 0; i < alliframes.length; i++) { for (let i = 0; i < alliframes.length; i++) {
const element = alliframes[i]; const element = alliframes[i];
if (element.getAttribute("excludeDarkCheck") == "true") {
continue;
}
element.contentDocument.documentElement.childNodes[1].style.color = element.contentDocument.documentElement.childNodes[1].style.color =
"white"; "white";
element.contentDocument.documentElement.firstChild.appendChild( element.contentDocument.documentElement.firstChild.appendChild(
@@ -2145,6 +2175,11 @@ function AddBetterSEQTAElements(toggle) {
for (let i = 0; i < alliframes.length; i++) { for (let i = 0; i < alliframes.length; i++) {
const element = alliframes[i]; const element = alliframes[i];
if (element.getAttribute("excludeDarkCheck") == "true") {
continue;
}
element.contentDocument.documentElement.childNodes[1].style.color = element.contentDocument.documentElement.childNodes[1].style.color =
"black"; "black";
element.contentDocument.documentElement.firstChild.lastChild.remove(); element.contentDocument.documentElement.firstChild.lastChild.remove();
@@ -2168,7 +2203,7 @@ function AddBetterSEQTAElements(toggle) {
var AddedSettings = document.getElementById("AddedSettings"); var AddedSettings = document.getElementById("AddedSettings");
var extensionsettings = document.getElementById("ExtensionPopup"); var extensionsettings = document.getElementById("ExtensionPopup");
AddedSettings.addEventListener("click", function () { AddedSettings.addEventListener("click", function () {
extensionsettings.classList.toggle("hidden"); extensionsettings.classList.toggle("hide");
SettingsClicked = true; SettingsClicked = true;
}); });
} }
@@ -2275,23 +2310,38 @@ function CheckCurrentLesson(lesson, num) {
} }
} }
function hexToRGB(hex) { function GetThresholdofHex(color) {
try { // Regular expression for matching RGBA colors
var r = parseInt(hex.slice(1, 3), 16), const rgbaRegex = /rgba?\(([^)]+)\)/g;
g = parseInt(hex.slice(3, 5), 16),
b = parseInt(hex.slice(5, 7), 16);
return { r: r, g: g, b: b }; // Check if the color string is a gradient (linear or radial)
} catch { if (color.includes("gradient")) {
// do nothing becuase this functoin is a bit broken right now (feel free to fix it!) let gradient = color;
// Find and replace all instances of RGBA in the gradient
let match;
while ((match = rgbaRegex.exec(color)) !== null) {
// Extract the individual components (r, g, b, a)
const rgbaString = match[1];
const [r, g, b, a] = rgbaString.split(",").map(str => str.trim());
// Compute the threshold using your existing algorithm
const threshold = Math.sqrt(r ** 2 + g ** 2 + b ** 2);
// Replace the original RGBA string with the computed threshold
// Note: You can modify this part based on what you actually want to do with the threshold
gradient = gradient.replace(`rgba(${rgbaString})`, `rgba(${threshold}, ${threshold}, ${threshold}, ${a})`);
}
return gradient;
} else {
// Handle the color as a simple RGBA (or hex, or whatever the Color library supports)
const rgb = Color.rgb(color).string();
return Math.sqrt(rgb.r ** 2 + rgb.g ** 2 + rgb.b ** 2);
} }
} }
function GetThresholdofHex(hex) {
var rgb = hexToRGB(hex);
return Math.sqrt(rgb.r ** 2 + rgb.g ** 2 + rgb.b ** 2);
}
function CheckCurrentLessonAll(lessons) { function CheckCurrentLessonAll(lessons) {
// Checks each lesson and sets an interval to run every 60 seconds to continue updating // Checks each lesson and sets an interval to run every 60 seconds to continue updating
LessonInterval = setInterval( LessonInterval = setInterval(
+38 -7
View File
@@ -15,7 +15,7 @@ chrome.runtime.onMessage.addListener(function (request) {
ReloadSEQTAPages(); ReloadSEQTAPages();
} else if (request.type == "githubTab") { } else if (request.type == "githubTab") {
chrome.tabs.create({ chrome.tabs.create({
url: "github.com/SethBurkart123/BetterThanBetterSeqta", url: "github.com/SethBurkart123/EvenBetterSEQTA",
}); });
} else if (request.type == "setDefaultStorage") { } else if (request.type == "setDefaultStorage") {
console.log("setting default values"); console.log("setting default values");
@@ -102,7 +102,6 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(TodayFormatted); console.log(TodayFormatted);
console.log(from); console.log(from);
// var url = `https://newsapi.org/v2/everything?sources=abc-news&from=${TodayFormatted}&sortBy=popularity&apiKey=17c0da766ba347c89d094449504e3080`;
var url = `https://newsapi.org/v2/everything?domains=abc.net.au&from=${from}&apiKey=17c0da766ba347c89d094449504e3080`; var url = `https://newsapi.org/v2/everything?domains=abc.net.au&from=${from}&apiKey=17c0da766ba347c89d094449504e3080`;
GetNews(url, sendResponse); GetNews(url, sendResponse);
@@ -168,7 +167,7 @@ const DefaultValues = {
enabled: false, enabled: false,
}, },
{ {
Name: "educationperfect", name: "educationperfect",
enabled: true, enabled: true,
}, },
], ],
@@ -217,13 +216,45 @@ function UpdateCurrentValues(details) {
}); });
} }
function migrateOldStorage() {
chrome.storage.local.get(null, function (items) {
let shouldUpdate = false; // Flag to check if there is anything to update
// Check for the old "Name" field and convert it to "name"
if (items.shortcuts && items.shortcuts.length > 0 && "Name" in items.shortcuts[0]) {
shouldUpdate = true;
items.shortcuts = items.shortcuts.map((shortcut) => {
return {
name: shortcut.Name, // Convert "Name" to "name"
enabled: shortcut.enabled // Keep the "enabled" field as is
};
});
}
// Check for "educationperfect" and convert it to "Education Perfect"
if (items.shortcuts && items.shortcuts.length > 0) {
for (let shortcut of items.shortcuts) {
if (shortcut.name === "educationperfect") {
shouldUpdate = true;
shortcut.name = "Education Perfect"; // Convert to "Education Perfect"
}
}
}
// If there's something to update, set the new values in storage
if (shouldUpdate) {
chrome.storage.local.set({ shortcuts: items.shortcuts }, function() {
console.log("Migration completed.");
});
}
});
}
chrome.runtime.onInstalled.addListener(function (event) { chrome.runtime.onInstalled.addListener(function (event) {
chrome.storage.local.remove(["justupdated"]); chrome.storage.local.remove(["justupdated"]);
UpdateCurrentValues(); UpdateCurrentValues();
if ( if ( event.reason == "install" ) {
/*chrome.runtime.getManifest().version > event.previousVersion || */ event.reason ==
"install"
) {
chrome.storage.local.set({ justupdated: true }); chrome.storage.local.set({ justupdated: true });
migrateOldStorage();
} }
}); });
+47 -54
View File
@@ -2,7 +2,6 @@
@import "./injected/popup.css"; @import "./injected/popup.css";
:root { :root {
background-color: var(--better-main) !important;
background: var(--better-main) !important; background: var(--better-main) !important;
--navy: #1a1a1a !important; --navy: #1a1a1a !important;
--auto-background: var(--better-pale, var(--background-secondary)) !important; --auto-background: var(--better-pale, var(--background-secondary)) !important;
@@ -15,7 +14,7 @@ html {
#container { #container {
transition: 200ms; transition: 200ms;
background-color: var(--auto-background) !important; background: var(--auto-background) !important;
} }
* { * {
@@ -23,11 +22,6 @@ html {
--theme-fg-parts: white; --theme-fg-parts: white;
} }
#title {
color: var(--text-primary);
font-weight: 500 !important;
}
@media (min-width: 900px) { @media (min-width: 900px) {
#title > span { #title > span {
transform: translateY(2px); transform: translateY(2px);
@@ -220,7 +214,7 @@ li.item.draggable {
} }
html { html {
background-color: var(--better-main) !important; background: var(--better-main) !important;
} }
/* Messages */ /* Messages */
@@ -270,29 +264,29 @@ ol:has(.MessageList__avatar___2wxyb svg) {
} }
.content [autocomplete="off"] { .content [autocomplete="off"] {
background-color: var(--background-primary) !important; background: var(--background-primary) !important;
} }
.MessageList__MessageList___3DxoC .footer { .MessageList__MessageList___3DxoC .footer {
background-color: var(--background-secondary) !important; background: var(--background-secondary) !important;
} }
.content [placeholder="Subject…"] { .content [placeholder="Subject…"] {
border-radius: 16px; border-radius: 16px;
padding-left: 12px !important; padding-left: 12px !important;
background-color: var(--background-primary) !important; background: var(--background-primary) !important;
} }
.listWrapper { .listWrapper {
padding: 8px; padding: 8px;
border-top-left-radius: 16px; border-top-left-radius: 16px;
border-top-right-radius: 16px; border-top-right-radius: 16px;
background-color: var(--background-primary); background: var(--background-primary);
margin-top: 26%; margin-top: 26%;
} }
.functions { .functions {
background-color: var(--background-primary); background: var(--background-primary);
margin: 0 !important; margin: 0 !important;
border-bottom-left-radius: 16px; border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px; border-bottom-right-radius: 16px;
@@ -468,7 +462,7 @@ ol > [data-label] {
.Viewer__newMessage___3ToUb { .Viewer__newMessage___3ToUb {
border-radius: 0.5rem !important; border-radius: 0.5rem !important;
font-size: 0.8rem !important; font-size: 0.8rem !important;
background-color: var(--background-primary) !important; background: var(--background-primary) !important;
} }
.MessageList__sender___32riy :last-child { .MessageList__sender___32riy :last-child {
@@ -509,7 +503,7 @@ div > ol:has(.uiFileHandlerWrapper) {
} }
#main > .timetablepage > .container { #main > .timetablepage > .container {
background-color: var(--background-primary); background: var(--background-primary);
} }
#content { #content {
@@ -557,20 +551,19 @@ div > ol:has(.uiFileHandlerWrapper) {
top: 0; top: 0;
width: 100%; width: 100%;
height: 100vh; height: 100vh;
background-repeat: no-repeat;
background-position: center;
background-position: 10% 10%;
color: var(--text-primary) !important; color: var(--text-primary) !important;
} }
.Module__wrapper___2sbOo { .Module__wrapper___2sbOo {
overflow: clip;
background: var(--background-primary) !important; background: var(--background-primary) !important;
border-radius: 1rem !important;
color: var(--text-primary) !important; color: var(--text-primary) !important;
box-shadow: none; box-shadow: none;
} }
.course .composer { .course .composer {
background: var(--background-primary) !important; background: transparent !important;
overflow: hidden; overflow: hidden;
} }
@@ -579,7 +572,7 @@ div > ol:has(.uiFileHandlerWrapper) {
> .Container__container___33GlY > .Container__container___33GlY
> .Document__document___1KJCG > .Document__document___1KJCG
> .Canvas__canvas___OBdCZ { > .Canvas__canvas___OBdCZ {
background-color: unset !important; background-color: transparent !important;
background-image: unset !important; background-image: unset !important;
color: white !important; color: white !important;
} }
@@ -607,20 +600,18 @@ div > ol:has(.uiFileHandlerWrapper) {
#title { #title {
background: var(--background-primary); background: var(--background-primary);
color: var(--text-primary);
height: 4rem; height: 4rem;
box-shadow: rgb(0 0 0 / 35%) 0px 0px 10px;
min-height: 48px; min-height: 48px;
box-shadow: rgb(0 0 0 / 35%) 0px 0px 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1); border-bottom: 1px solid rgba(255, 255, 255, 0.1);
font-weight: 500 !important;
z-index: 1; z-index: 1;
} }
.bg { .bg {
animation: slide 3s ease-in-out infinite alternate; animation: slide 3s ease-in-out infinite alternate;
background-image: linear-gradient( background: var(--better-main);
-60deg,
var(--better-main) 50%,
var(--auto-background) 50%
);
bottom: 0; bottom: 0;
left: -50%; left: -50%;
opacity: 0.5; opacity: 0.5;
@@ -629,6 +620,7 @@ div > ol:has(.uiFileHandlerWrapper) {
top: 0; top: 0;
z-index: 0 !important; z-index: 0 !important;
overflow: hidden; overflow: hidden;
scale: 1.5;
} }
.bg2 { .bg2 {
@@ -642,11 +634,11 @@ div > ol:has(.uiFileHandlerWrapper) {
@keyframes slide { @keyframes slide {
0% { 0% {
transform: translateX(-25%); transform: translate(50%) rotate(-60deg);
} }
100% { 100% {
transform: translateX(25%); transform: translateX(5%) rotate(-60deg);
} }
} }
@@ -694,7 +686,7 @@ div > ol:has(.uiFileHandlerWrapper) {
font-size: 3em !important; font-size: 3em !important;
font-weight: 300; font-weight: 300;
margin: 30px auto 60px; margin: 30px auto 60px;
background-color: var(--background-primary); background: var(--background-primary);
height: 3em; height: 3em;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -708,7 +700,7 @@ div > ol:has(.uiFileHandlerWrapper) {
width: 94%; width: 94%;
margin: 50px auto; margin: 50px auto;
height: 19em; height: 19em;
background-color: var(--better-main); background: var(--better-main);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
-webkit-box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; -webkit-box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
@@ -716,7 +708,7 @@ div > ol:has(.uiFileHandlerWrapper) {
} }
.day-container { .day-container {
background-color: var(--background-primary); background: var(--background-primary);
transition: 200ms; transition: 200ms;
width: 100%; width: 100%;
height: 15em; height: 15em;
@@ -729,7 +721,7 @@ div > ol:has(.uiFileHandlerWrapper) {
width: 94%; width: 94%;
margin: 50px auto; margin: 50px auto;
max-height: 60em; max-height: 60em;
background-color: var(--better-main); background: var(--better-main);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
-webkit-box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; -webkit-box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
@@ -737,7 +729,7 @@ div > ol:has(.uiFileHandlerWrapper) {
} }
.notice-container { .notice-container {
background-color: var(--better-main); background: var(--better-main);
width: 100%; width: 100%;
max-height: 55em; max-height: 55em;
overflow-y: auto; overflow-y: auto;
@@ -789,7 +781,7 @@ div > ol:has(.uiFileHandlerWrapper) {
border: 2px solid var(--better-main); border: 2px solid var(--better-main);
width: 94%; width: 94%;
margin: 10px auto 50px; margin: 10px auto 50px;
background-color: var(--better-main); background: var(--better-main);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
-webkit-box-shadow: 0px 5px 16px 6px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 5px 16px 6px rgba(0, 0, 0, 0.3);
@@ -807,7 +799,7 @@ div > ol:has(.uiFileHandlerWrapper) {
} }
.shortcuts { .shortcuts {
background-color: var(--better-main); background: var(--better-main);
width: 100%; width: 100%;
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
@@ -991,13 +983,13 @@ div > ol:has(.uiFileHandlerWrapper) {
} }
.modaliser { .modaliser {
background-color: var(--better-main); background: var(--better-main);
} }
.alert-container { .alert-container {
height: 35em; height: 35em;
width: 22em; width: 22em;
background-color: var(--better-sub); background: var(--better-sub);
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
@@ -1081,7 +1073,7 @@ div > ol:has(.uiFileHandlerWrapper) {
#ExtensionPopup { #ExtensionPopup {
border-radius: 1rem; border-radius: 1rem;
box-shadow: 0px 10px 15px -3px rgba(0, 0, 0, 0.4); box-shadow: 0px 0px 20px -2px rgba(0,0,0,0.6)
} }
#menu li.active { #menu li.active {
@@ -1171,7 +1163,7 @@ div > ol:has(.uiFileHandlerWrapper) {
.Input__Input___3RSTI { .Input__Input___3RSTI {
transition: background-color 0.5s,border-color 0.5s; transition: background-color 0.5s,border-color 0.5s;
background-color: var(--auto-background); background: var(--auto-background);
position: relative; position: relative;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
border-radius: 0.5rem; border-radius: 0.5rem;
@@ -1245,7 +1237,7 @@ iframe.userHTML {
.Thermoscore__Thermoscore___2tWMi { .Thermoscore__Thermoscore___2tWMi {
background-image: unset; background-image: unset;
background-color: var(--auto-background); background: var(--auto-background);
} }
#toolbar { #toolbar {
@@ -1275,6 +1267,7 @@ iframe.userHTML {
#main > .course > .content > h1 { #main > .course > .content > h1 {
color: var(--text-primary); color: var(--text-primary);
border-bottom: none;
} }
#main > .course > .content > .outline > h2, #main > .course > .content > .outline > h2,
@@ -1291,7 +1284,7 @@ iframe.userHTML {
::-webkit-scrollbar-thumb:vertical:hover, ::-webkit-scrollbar-thumb:vertical:hover,
::-webkit-scrollbar-thumb:horizontal:hover { ::-webkit-scrollbar-thumb:horizontal:hover {
background-color: var(--better-light); background: var(--better-light);
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
@@ -1381,16 +1374,16 @@ ul {
} }
.legacy-root .uiFileHandler { .legacy-root .uiFileHandler {
background-color: var(--auto-background); background: var(--auto-background);
border-radius: 1rem; border-radius: 1rem;
} }
.ResourceList__ResourceList___2z-c1 .legacy-root .uiFileHandler { .ResourceList__ResourceList___2z-c1 .legacy-root .uiFileHandler {
background-color: var(--background-primary); background: var(--background-primary);
} }
.legacy-root .uiFileHandler.dragTarget { .legacy-root .uiFileHandler.dragTarget {
background-color: var(--better-main); background: var(--better-main);
} }
.MenuButton__MenuPanel___2q42B { .MenuButton__MenuPanel___2q42B {
@@ -1497,13 +1490,13 @@ blurred {
} }
.uiSlidePane > .pane > .header { .uiSlidePane > .pane > .header {
background-color: var(--better-main); background: var(--better-main);
} }
.content [placeholder="Subject…"] { .content [placeholder="Subject…"] {
padding-left: 12px !important; padding-left: 12px !important;
border-radius: 1rem; border-radius: 1rem;
background-color: var(--background-primary) !important; background: var(--background-primary) !important;
color: var(--text-primary) !important; color: var(--text-primary) !important;
} }
@@ -1523,7 +1516,7 @@ blurred {
} }
.formattedText > .footer { .formattedText > .footer {
background-color: var(--background-primary); background: var(--background-primary);
border-radius: 1rem; border-radius: 1rem;
margin-top: 0.5rem; margin-top: 0.5rem;
} }
@@ -1544,7 +1537,7 @@ blurred {
.uiSlidePane > .pane { .uiSlidePane > .pane {
color: var(--text-primary); color: var(--text-primary);
background-color: var(--auto-background); background: var(--auto-background);
transform: translateY(100%); transform: translateY(100%);
transition: transition:
transform 0.5s ease-in-out, transform 0.5s ease-in-out,
@@ -1672,7 +1665,7 @@ body {
} }
.MessageList__MessageList___3DxoC > ol > li.MessageList__unread___3imtO { .MessageList__MessageList___3DxoC > ol > li.MessageList__unread___3imtO {
box-shadow: inset 3px 0 rgb(255, 255, 255); box-shadow: inset 3px 0 var(--better-main);
} }
.connectedNotificationsWrapper > div > button { .connectedNotificationsWrapper > div > button {
@@ -2054,7 +2047,7 @@ body {
width: 94%; width: 94%;
margin: 50px auto; margin: 50px auto;
max-height: 60em; max-height: 60em;
background-color: var(--better-main); background: var(--better-main);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
-webkit-box-shadow: 0px 5px 16px 6px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 5px 16px 6px rgba(0, 0, 0, 0.3);
@@ -2226,7 +2219,7 @@ body {
/* When the checkbox is checked, add a blue background */ /* When the checkbox is checked, add a blue background */
.upcoming-checkbox-container input:checked ~ .upcoming-checkmark { .upcoming-checkbox-container input:checked ~ .upcoming-checkmark {
background-color: var(--item-colour); background: var(--item-colour);
} }
/* Create the checkmark/indicator (hidden when not checked) */ /* Create the checkmark/indicator (hidden when not checked) */
@@ -2378,7 +2371,7 @@ body {
} }
.upcoming-items { .upcoming-items {
background-color: var(--background-primary); background: var(--background-primary);
transition: 200ms; transition: 200ms;
width: 100%; width: 100%;
max-height: 55em; max-height: 55em;
@@ -2532,7 +2525,7 @@ body {
/* When the checkbox is checked, add a blue background */ /* When the checkbox is checked, add a blue background */
.upcoming-checkbox-container input:checked ~ .upcoming-checkmark { .upcoming-checkbox-container input:checked ~ .upcoming-checkmark {
background-color: var(--item-colour); background: var(--item-colour);
} }
/* Create the checkmark/indicator (hidden when not checked) */ /* Create the checkmark/indicator (hidden when not checked) */
@@ -2668,7 +2661,7 @@ body {
transform: scale(0); transform: scale(0);
transition: transform 0.2s; transition: transform 0.2s;
transform-origin: top; transform-origin: top;
background-color: var(--background-primary); background: var(--background-primary);
color: var(--text-primary); color: var(--text-primary);
text-align: center; text-align: center;
border-radius: 6px; border-radius: 6px;
+5
View File
@@ -5,3 +5,8 @@
.topmenu { .topmenu {
margin-top: 0; margin-top: 0;
} }
.hide {
opacity: 0;
pointer-events: none;
}
+5
View File
@@ -0,0 +1,5 @@
export function StorageListner() {
chrome.storage.onChanged.addListener(function (changes) {
}
}
+22
View File
@@ -0,0 +1,22 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
important: true,
darkMode: "class",
theme: {
fontSize: {
"xs": ".65rem",
"sm": ".775rem",
"base": "0.65rem",
"md": "0.65rem",
"lg": "1rem",
"xl": "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
}
},
plugins: [],
};
+23
View File
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ES2016",
"useDefineForClassFields": true,
"lib": ["ES2016", "DOM", "DOM.Iterable"],
"module": "ES2015",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": false,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
}
+1
View File
@@ -64,6 +64,7 @@ export default {
{ from: "public", to: "." }, { from: "public", to: "." },
{ from: "src/inject/preview", to: "inject/preview" }, { from: "src/inject/preview", to: "inject/preview" },
{ from: "node_modules/webextension-polyfill/dist/browser-polyfill.js", to: "."}, { from: "node_modules/webextension-polyfill/dist/browser-polyfill.js", to: "."},
{ from: "interface/dist/client", to: "client" }
], ],
}), }),
], ],