diff --git a/interface/package.json b/interface/package.json index fe8cd0e8..b6e4fc0b 100644 --- a/interface/package.json +++ b/interface/package.json @@ -13,7 +13,7 @@ "@types/chrome": "^0.0.246", "framer-motion": "^10.16.4", "react": "^18.2.0", - "react-best-gradient-color-picker": "^2.2.22", + "react-best-gradient-color-picker": "^2.2.23", "react-dom": "^18.2.0" }, "devDependencies": { diff --git a/interface/src/App.tsx b/interface/src/App.tsx index 2ef6918a..87b3deec 100644 --- a/interface/src/App.tsx +++ b/interface/src/App.tsx @@ -6,6 +6,7 @@ import logoDark from './assets/betterseqta-light-full.png'; import Shortcuts from './pages/Shortcuts'; import About from './pages/About'; import { SettingsContextProvider } from './SettingsContext'; +import Picker from './components/Picker'; const App: React.FC = () => { @@ -32,6 +33,7 @@ const App: React.FC = () => { + diff --git a/interface/src/SettingsContext.tsx b/interface/src/SettingsContext.tsx index 302cf2aa..93135a27 100644 --- a/interface/src/SettingsContext.tsx +++ b/interface/src/SettingsContext.tsx @@ -7,6 +7,8 @@ import useSettingsState from './hooks/settingsState'; const SettingsContext = createContext<{ settingsState: SettingsState; setSettingsState: React.Dispatch>; + showPicker: boolean; + setShowPicker: React.Dispatch>; } | undefined>(undefined); export const SettingsContextProvider: React.FC<{ children: ReactNode }> = ({ children }) => { @@ -15,15 +17,18 @@ export const SettingsContextProvider: React.FC<{ children: ReactNode }> = ({ chi lessonAlerts: false, animatedBackground: false, animatedBackgroundSpeed: "0", - customThemeColor: "#db6969", + customThemeColor: "rgba(219, 105, 105, 1)", betterSEQTAPlus: true, - shortcuts: [] + shortcuts: [], + customshortcuts: [], }); + const [showPicker, setShowPicker] = useState(false); + useSettingsState({ settingsState, setSettingsState }); return ( - + {children} ); diff --git a/interface/src/components/ColorPicker.tsx b/interface/src/components/ColorPicker.tsx deleted file mode 100644 index b9b6ee80..00000000 --- a/interface/src/components/ColorPicker.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-expect-error There aren't any types for the below library -import ColorPicker from 'react-best-gradient-color-picker'; -import { useState, useRef, useEffect } from 'react'; -import type { ColorPickerProps } from '../types/ColorPickerProps'; - -const Picker = ({ color, onChange }: ColorPickerProps) => { - const [showPicker, setShowPicker] = useState(false); - const ref = useRef(null); - - useEffect(() => { - const handleClickOutside = (event: MouseEvent): void => { - if (ref.current && !ref.current.contains(event.target as Node)) { - setShowPicker(false); - } - }; - if (showPicker) { - document.addEventListener('mousedown', handleClickOutside); - } - return () => { - document.removeEventListener('mousedown', handleClickOutside); - }; - }, [showPicker]); - - return ( - <> - - {showPicker && ( -
-
- -
-
- )} - - ); -}; - -export default Picker; diff --git a/interface/src/components/Picker.tsx b/interface/src/components/Picker.tsx new file mode 100644 index 00000000..19d06478 --- /dev/null +++ b/interface/src/components/Picker.tsx @@ -0,0 +1,56 @@ +// @ts-expect-error There aren't any types for the below library +import ColorPicker from 'react-best-gradient-color-picker'; +import { useSettingsContext } from '../SettingsContext'; +import { motion } from "framer-motion"; + +export default function Picker() { + const { settingsState, setSettingsState, showPicker, setShowPicker } = useSettingsContext(); + + const colorChange = (color: string) => { + setSettingsState({ + ...settingsState, + customThemeColor: color, + }); + }; + + // Define animation variants + const backgroundVariants = { + hidden: { opacity: 0 }, + visible: { opacity: 1 }, + exit: { opacity: 0 } + }; + + const scaleVariants = { + hidden: { scale: 0.3 }, + visible: { scale: 1 }, + exit: { scale: 0.4 } // Adding exit animation + }; + + return ( + // Apply fade-in animation to background + setShowPicker(false)} + className={`absolute top-0 left-0 z-50 flex justify-center w-full h-full pt-4 bg-black/20 ${!showPicker ? 'pointer-events-none' : ''}`} + > +
+ {/* Apply springy scale animation */} + e.stopPropagation()} + className="h-auto p-4 bg-white border rounded-lg shadow-lg dark:bg-zinc-800 border-zinc-100 dark:border-zinc-700" + > + + +
+
+ ); +} \ No newline at end of file diff --git a/interface/src/components/PickerSwatch.tsx b/interface/src/components/PickerSwatch.tsx new file mode 100644 index 00000000..48eb9c03 --- /dev/null +++ b/interface/src/components/PickerSwatch.tsx @@ -0,0 +1,19 @@ +import { useSettingsContext } from '../SettingsContext'; + +const PickerSwatch = () => { + const { setShowPicker, settingsState } = useSettingsContext(); + + const enablePicker = () => { + setShowPicker(true); + }; + + return ( + + ); +}; + +export default PickerSwatch; diff --git a/interface/src/main.d.ts b/interface/src/main.d.ts index f94c3d5e..dc61163c 100644 --- a/interface/src/main.d.ts +++ b/interface/src/main.d.ts @@ -4,3 +4,5 @@ declare module "*.png"; declare module "*.svg"; declare module "*.jpeg"; declare module "*.jpg"; + +declare module 'react-best-gradient-color-picker'; \ No newline at end of file diff --git a/interface/src/main.tsx b/interface/src/main.tsx index 231d01e2..89f15c06 100644 --- a/interface/src/main.tsx +++ b/interface/src/main.tsx @@ -1,10 +1,20 @@ -import React from 'react' +import React, { useState } from 'react' import ReactDOM from 'react-dom/client' import App from './App.js' import './index.css' +// @ts-expect-error There aren't any types for the below library +import ColorPicker from 'react-best-gradient-color-picker'; const root = ReactDOM.createRoot(document.getElementById('ExtensionPopup')!); +// @ts-expect-error woaefoiahef +// eslint-disable-next-line +function Testing() { + const [color, setColor] = useState('#fffff'); + + return +} + root.render( diff --git a/interface/src/pages/Settings.tsx b/interface/src/pages/Settings.tsx index 6841671d..b116f960 100644 --- a/interface/src/pages/Settings.tsx +++ b/interface/src/pages/Settings.tsx @@ -1,6 +1,6 @@ -import ColorPicker from '../components/ColorPicker'; import Switch from '../components/Switch'; import Slider from '../components/Slider'; +import PickerSwatch from '../components/PickerSwatch'; import { SettingsList } from '../types/SettingsProps'; import { useSettingsContext } from '../SettingsContext'; @@ -20,13 +20,6 @@ const Settings: React.FC = () => { ...settingsState, [key]: value, }); - } - - const colorChange = (color: string) => { - setSettingsState({ - ...settingsState, - customThemeColor: color, - }); }; const settings: SettingsList[] = [ @@ -53,7 +46,7 @@ const Settings: React.FC = () => { { title: "Custom Theme Colour", description: "Customise the overall theme colour of SEQTA Learn.", - modifyElement: colorChange(color)} /> + modifyElement: }, { title: "BetterSEQTA+", diff --git a/interface/src/types/ColorPickerProps.ts b/interface/src/types/ColorPickerProps.ts index 5eda91c8..ae888971 100644 --- a/interface/src/types/ColorPickerProps.ts +++ b/interface/src/types/ColorPickerProps.ts @@ -1,4 +1,5 @@ export interface ColorPickerProps { color: string; onChange: (color: string) => void; + id: string; } \ No newline at end of file diff --git a/src/SEQTA.js b/src/SEQTA.js index ff14e0bd..87f1535c 100644 --- a/src/SEQTA.js +++ b/src/SEQTA.js @@ -9,7 +9,7 @@ import loading, { AppendLoadingSymbol } from "./seqta/ui/Loading.js"; // Icons import assessmentsicon from "./seqta/icons/assessmentsIcon.js"; import coursesicon from "./seqta/icons/coursesIcon.js"; -import StorageListener from "./seqta/utils/StorageListener"; +import StorageListener from "./seqta/utils/StorageListener.js"; let isChrome = window.chrome; let SettingsClicked = false; @@ -691,10 +691,17 @@ export function ColorLuminance(color, lum = 0) { if (color.includes("gradient")) { let gradient = color; - // Find and replace all instances of RGBA in the gradient + // Create a set to hold unique RGBA strings + let uniqueRgbaSet = new Set(); + + // Find all instances of RGBA in the gradient let match; while ((match = rgbaRegex.exec(color)) !== null) { - const rgbaString = match[1]; + uniqueRgbaSet.add(match[1]); // Add the unique RGBA string to the set + } + + // Loop through each unique RGBA string + for (let rgbaString of uniqueRgbaSet) { const [r, g, b, a] = rgbaString.split(",").map(str => str.trim()); // Apply the original luminance adjustment logic @@ -705,8 +712,9 @@ export function ColorLuminance(color, lum = 0) { } 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(", ")})`); + // Replace all occurrences of the original RGBA string with the adjusted one + const regex = new RegExp(`rgba\\(${rgbaString}\\)`, "g"); + gradient = gradient.replace(regex, `rgba(${adjustedRgba.join(", ")})`); } return gradient; @@ -1280,261 +1288,13 @@ function CallExtensionSettings() { fileref.setAttribute("href", cssFile); document.head.append(fileref); - /*let Settings = - stringToHTML( - String.raw` - `);*/ - let Settings2 = + let Settings = stringToHTML( String.raw`
`); - document.body.append(Settings2.firstChild); + document.body.append(Settings.firstChild); // add an iframe to the div: let iframe = document.createElement("iframe"); @@ -2938,9 +2698,8 @@ function SendHomePage() { currentSelectedDate = new Date(); // Creates the root of the home page added to the main div - var htmlStr = "
"; - - var html = stringToHTML(htmlStr); + var html = stringToHTML("
"); + // Appends the html file to main div // Note : firstChild of html is done due to needing to grab the body from the stringToHTML function main.append(html.firstChild); diff --git a/src/inject/injected.css b/src/inject/injected.css index 50bb2440..b2b06bc2 100644 --- a/src/inject/injected.css +++ b/src/inject/injected.css @@ -1171,6 +1171,7 @@ div > ol:has(.uiFileHandlerWrapper) { .Avatar__Avatar___gE5kx.Avatar__staff___4gVLs { --person-colour: var(--better-light); + background: var(--person-colour, var(--navy)); } .LabelList__LabelList___2RJFf > li.LabelList__selected___3Egk7 { diff --git a/src/seqta/utils/StorageListener.js b/src/seqta/utils/StorageListener.js index d788db07..6ef8907e 100644 --- a/src/seqta/utils/StorageListener.js +++ b/src/seqta/utils/StorageListener.js @@ -1,5 +1,5 @@ /* global chrome */ -import { lightenAndPaleColor, GetThresholdofHex, ColorLuminance, CreateCustomShortcutDiv, RemoveCustomShortcutDiv } from "../../SEQTA"; +import { lightenAndPaleColor, GetThresholdofHex, ColorLuminance, CreateCustomShortcutDiv, RemoveCustomShortcutDiv } from "../../SEQTA.js"; export default function StorageListener() { chrome.storage.onChanged.addListener(function (changes) {