mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
fix settings
This commit is contained in:
+6
-26
@@ -7,45 +7,25 @@ import logoDark from './assets/betterseqta-light-full.png';
|
||||
import Shortcuts from './pages/Shortcuts';
|
||||
import About from './pages/About';
|
||||
|
||||
export interface SettingsState {
|
||||
notificationCollector: boolean;
|
||||
lessonAlerts: boolean;
|
||||
animatedBackground: boolean;
|
||||
animatedBackgroundSpeed: boolean;
|
||||
customThemeColor: string;
|
||||
betterSEQTAPlus: boolean;
|
||||
}
|
||||
import type { SettingsState } from './types/AppProps';
|
||||
import useSettingsState from './hooks/settingsState';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [settingsState, setSettingsState] = useState<SettingsState>({
|
||||
notificationCollector: false,
|
||||
lessonAlerts: false,
|
||||
animatedBackground: false,
|
||||
animatedBackgroundSpeed: false,
|
||||
animatedBackgroundSpeed: "0",
|
||||
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,
|
||||
});
|
||||
};
|
||||
useSettingsState({ settingsState, setSettingsState });
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
title: 'Settings',
|
||||
content: <Settings settingsState={settingsState} switchChange={switchChange} colorChange={colorChange} />
|
||||
content: <Settings settingsState={settingsState} setSettingsState={setSettingsState} />
|
||||
},
|
||||
{
|
||||
title: 'Shortcuts',
|
||||
@@ -59,7 +39,7 @@ const App: React.FC = () => {
|
||||
|
||||
{/* <div className="flex justify-center w-screen h-screen pt-4 overflow-hidden" style={{ background: settingsState.customThemeColor }}> */}
|
||||
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">
|
||||
<div className="flex flex-col w-[384px] shadow-2xl gap-2 bg-white rounded-xl h-[590px] dark:bg-zinc-800 dark:text-white">
|
||||
<div className="grid border-b border-b-zinc-200/40 place-items-center">
|
||||
<img src={logo} className="w-4/5 dark:hidden" />
|
||||
<img src={logoDark} className="hidden w-4/5 dark:block" />
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
interface ColorPickerProps {
|
||||
color: string;
|
||||
onChange: (color: string) => void;
|
||||
}
|
||||
declare const Picker: ({ color, onChange }: ColorPickerProps) => import("react/jsx-runtime").JSX.Element;
|
||||
export default Picker;
|
||||
@@ -1,10 +1,7 @@
|
||||
// @ts-expect-error There aren't any types for the below library
|
||||
import ColorPicker from 'react-best-gradient-color-picker';
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
|
||||
interface ColorPickerProps {
|
||||
color: string;
|
||||
onChange: (color: string) => void;
|
||||
}
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import type { ColorPickerProps } from '../types/ColorPicker';
|
||||
|
||||
const Picker = ({ color, onChange }: ColorPickerProps) => {
|
||||
const [showPicker, setShowPicker] = useState<boolean>(false);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import "./Slider.css";
|
||||
|
||||
interface Slider {
|
||||
onValueChange: (value: number) => void;
|
||||
}
|
||||
import type { Slider } from '../types/Slider';
|
||||
|
||||
const Slider: React.FC<Slider> = ({ onValueChange }) => {
|
||||
const [sliderValue, setSliderValue] = useState(0);
|
||||
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
import "./Switch.css";
|
||||
interface SwitchProps {
|
||||
onChange: (isOn: boolean) => void;
|
||||
state: boolean;
|
||||
}
|
||||
export default function Switch(props: SwitchProps): import("react/jsx-runtime").JSX.Element;
|
||||
export {};
|
||||
@@ -1,10 +1,6 @@
|
||||
import { motion } from "framer-motion";
|
||||
import "./Switch.css";
|
||||
|
||||
interface SwitchProps {
|
||||
onChange: (isOn: boolean) => void;
|
||||
state: boolean;
|
||||
}
|
||||
import type { SwitchProps } from "../types/Switch";
|
||||
|
||||
export default function Switch(props: SwitchProps) {
|
||||
const toggleSwitch = () => {
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
interface Tab {
|
||||
title: string;
|
||||
content: JSX.Element;
|
||||
}
|
||||
|
||||
interface TabbedContainerProps {
|
||||
tabs: Tab[];
|
||||
themeColor: string;
|
||||
}
|
||||
import type { TabbedContainerProps } from '../types/TabbedContainer';
|
||||
|
||||
const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs, themeColor }) => {
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*global chrome*/
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { SettingsProps } from "../types/SettingsProps";
|
||||
import { MainConfig, SettingsState } from "../types/AppProps";
|
||||
|
||||
let RanOnce = false;
|
||||
type StorageKeyToStateKeyMap = {
|
||||
[key in keyof MainConfig]?: keyof SettingsState;
|
||||
};
|
||||
let previousSettingsState: SettingsState
|
||||
|
||||
const useSettingsState = ({ settingsState, setSettingsState }: SettingsProps) => {
|
||||
// run the following code once
|
||||
useEffect(() => {
|
||||
if (RanOnce) return;
|
||||
RanOnce = true;
|
||||
|
||||
// get the current settings state
|
||||
chrome.storage.local.get(function(result: MainConfig) {
|
||||
setSettingsState({
|
||||
notificationCollector: result.notificationcollector,
|
||||
lessonAlerts: result.lessonalert,
|
||||
animatedBackground: result.animatedbk,
|
||||
animatedBackgroundSpeed: result.bksliderinput,
|
||||
customThemeColor: result.selectedColor,
|
||||
betterSEQTAPlus: result.onoff
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const keyToStateMap = useMemo(() => ({
|
||||
"notificationcollector": "notificationCollector",
|
||||
"lessonalert": "lessonAlerts",
|
||||
"animatedbk": "animatedBackground",
|
||||
"bksliderinput": "animatedBackgroundSpeed",
|
||||
"selectedColor": "customThemeColor",
|
||||
"onoff": "betterSEQTAPlus",
|
||||
}), []);
|
||||
|
||||
const storageChangeListener = (changes: chrome.storage.StorageChange) => {
|
||||
for (const [key, { newValue }] of Object.entries(changes)) {
|
||||
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) => {
|
||||
console.log(chrome.storage.local.set({ [key]: value }));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log("settingsState", settingsState)
|
||||
console.log("previousSettingsState", previousSettingsState)
|
||||
if (previousSettingsState) {
|
||||
for (const [key, value] of Object.entries(settingsState)) {
|
||||
const storageKey = Object.keys(keyToStateMap).find(k => keyToStateMap[k] === key);
|
||||
if (storageKey && value !== previousSettingsState[key]) {
|
||||
console.log("key", storageKey)
|
||||
setStorage(storageKey as keyof MainConfig, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
previousSettingsState = settingsState;
|
||||
}, [settingsState, keyToStateMap])
|
||||
}
|
||||
|
||||
export default useSettingsState;
|
||||
@@ -1,21 +1,24 @@
|
||||
import Switch from '../components/Switch';
|
||||
import ColorPicker from '../components/ColorPicker';
|
||||
import { SettingsState } from '../../../src/popup/App';
|
||||
import { SettingsProps, SettingsList } from '../types/SettingsProps';
|
||||
|
||||
interface ISetting {
|
||||
title: string;
|
||||
description: string;
|
||||
modifyElement: JSX.Element;
|
||||
}
|
||||
const Settings: React.FC<SettingsProps> = ({ settingsState, setSettingsState }) => {
|
||||
|
||||
interface SettingsProps {
|
||||
settingsState: SettingsState;
|
||||
switchChange: (key: string, isOn: boolean) => void;
|
||||
colorChange: (color: string) => void;
|
||||
}
|
||||
const switchChange = (key: string, isOn: boolean) => {
|
||||
setSettingsState({
|
||||
...settingsState,
|
||||
[key]: isOn,
|
||||
});
|
||||
};
|
||||
|
||||
const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorChange }) => {
|
||||
const settings: ISetting[] = [
|
||||
const colorChange = (color: string) => {
|
||||
setSettingsState({
|
||||
...settingsState,
|
||||
customThemeColor: color,
|
||||
});
|
||||
};
|
||||
|
||||
const settings: SettingsList[] = [
|
||||
{
|
||||
title: "Notification Collector",
|
||||
description: "Uncaps the 9+ limit for notifications, showing the real number.",
|
||||
@@ -34,7 +37,7 @@ const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorC
|
||||
{
|
||||
title: "Animated Background Speed",
|
||||
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",
|
||||
@@ -43,7 +46,7 @@ const Settings: React.FC<SettingsProps> = ({ settingsState, switchChange, colorC
|
||||
},
|
||||
{
|
||||
title: "BetterSEQTA+",
|
||||
description: "Unlocks premium features.",
|
||||
description: "Enables BetterSEQTA+ features",
|
||||
modifyElement: <Switch state={settingsState.betterSEQTAPlus} onChange={(isOn: boolean) => switchChange('betterSEQTAPlus', isOn)} />
|
||||
}
|
||||
];
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
export interface SettingsState {
|
||||
notificationCollector: boolean;
|
||||
lessonAlerts: boolean;
|
||||
animatedBackground: boolean;
|
||||
animatedBackgroundSpeed: string;
|
||||
customThemeColor: string;
|
||||
betterSEQTAPlus: boolean;
|
||||
}
|
||||
|
||||
// Define the ToggleItem interface for the nested objects in menuitems
|
||||
interface ToggleItem {
|
||||
toggle: boolean;
|
||||
}
|
||||
|
||||
// Define the Shortcut interface for the objects in the shortcuts array
|
||||
interface Shortcut {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
||||
// Define the MainConfig interface for the top-level object
|
||||
export interface MainConfig {
|
||||
DarkMode: boolean;
|
||||
animatedbk: boolean;
|
||||
bksliderinput: string;
|
||||
customshortcuts: any[];
|
||||
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>; // Could be more specific based on what types are allowed
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ColorPickerProps {
|
||||
color: string;
|
||||
onChange: (color: string) => void;
|
||||
}
|
||||
@@ -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>>;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import "./Slider.css";
|
||||
interface Slider {
|
||||
export interface Slider {
|
||||
onValueChange: (value: number) => void;
|
||||
}
|
||||
declare const Slider: React.FC<Slider>;
|
||||
@@ -0,0 +1,6 @@
|
||||
import "./Switch.css";
|
||||
|
||||
export interface SwitchProps {
|
||||
onChange: (isOn: boolean) => void;
|
||||
state: boolean;
|
||||
}
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import React, { JSX } from 'react';
|
||||
interface Tab {
|
||||
export interface Tab {
|
||||
title: string;
|
||||
content: JSX.Element;
|
||||
}
|
||||
interface TabbedContainerProps {
|
||||
export interface TabbedContainerProps {
|
||||
tabs: Tab[];
|
||||
themeColor: string;
|
||||
}
|
||||
Reference in New Issue
Block a user