From f0c5b1dace47a5ca7f53bb573f12d7509f487dcc Mon Sep 17 00:00:00 2001 From: SethBurkart123 Date: Thu, 27 Mar 2025 21:31:41 +1100 Subject: [PATCH] feat: build themes into a centralised plugin --- plugins.md | 207 ------ .../components/store/Backgrounds.svelte | 6 +- .../components/themes/ThemeSelector.svelte | 26 +- src/interface/pages/store.svelte | 17 +- src/interface/pages/themeCreator.svelte | 28 +- src/plugins/built-in/themes/index.ts | 54 ++ src/plugins/built-in/themes/theme-manager.ts | 644 ++++++++++++++++++ src/plugins/index.ts | 2 + src/seqta/utils/listeners/MessageListener.ts | 34 +- themes.md | 123 ++++ 10 files changed, 877 insertions(+), 264 deletions(-) delete mode 100644 plugins.md create mode 100644 src/plugins/built-in/themes/index.ts create mode 100644 src/plugins/built-in/themes/theme-manager.ts create mode 100644 themes.md diff --git a/plugins.md b/plugins.md deleted file mode 100644 index 01ce9cf6..00000000 --- a/plugins.md +++ /dev/null @@ -1,207 +0,0 @@ -# BetterSEQTA+ Plugin System - -## Overview -The BetterSEQTA+ plugin system is designed to provide a clean, type-safe, and developer-friendly way to extend the functionality of BetterSEQTA+. While initially focused on built-in plugins, the architecture is designed to potentially support external plugins in the future. - -## Core Concepts - -### Plugin Structure -Each plugin is a simple object that contains metadata and a run function: - -```typescript -const examplePlugin = { - id: 'example', - name: 'Example Plugin', - description: 'Does something cool', - version: '1.0.0', - settings: { - enabled: { type: 'boolean', default: true }, - color: { type: 'string', default: '#ff0000' } - }, - - run: (api) => { - // Plugin logic here - } -}; -``` - -### Plugin API -Plugins receive a powerful API object that provides access to: - -- **Settings**: Type-safe settings management with direct property access -- **SEQTA Integration**: React component mounting and state management -- **Storage**: Persistent storage capabilities -- **Events**: Communication system - -### Settings System -Settings are defined with TypeScript types for safety and accessed like regular properties: - -```typescript -// In your plugin -api.settings.myOption = true; -const value = api.settings.myOption; - -// Watch for changes -api.settings.onChange('myOption', (newValue) => { - console.log('Option changed:', newValue); -}); -``` - -### SEQTA Integration -Plugins can interact with SEQTA's React components: - -```typescript -// Listen for component mounting -api.seqta.onMount('.timetable-view', (element) => { - // Access the DOM element directly - console.log('Timetable mounted:', element); - - // If you need React access, use getFiber - const fiber = api.seqta.getFiber('.timetable-view'); - fiber.setState(prevState => ({ - ...prevState, - someValue: true - })); -}); - -// Get specific component -const fiber = api.seqta.getFiber('.timetable-cell'); -const props = await fiber.getProps(); - -// Listen for page changes -api.seqta.onPageChange((page) => { - if (page === 'timetable') { - // Handle timetable page - } -}); -``` - -## Implementation Status - -### Phase 1: Core Infrastructure ✅ -- [x] Create basic plugin type definitions -- [x] Implement plugin manager -- [x] Set up basic API structure -- [x] Create plugin loading system - -### Phase 2: Settings System ✅ -- [x] Design settings storage structure -- [x] Implement settings proxy system -- [x] Add settings change notifications -- [x] Create settings validation - -### Phase 3: SEQTA Integration ✅ -- [x] Implement component mount detection -- [x] Create ReactFiber wrapper -- [x] Add page change detection -- [x] Create component state utilities - -### Phase 4: Plugin API Features ✅ -- [x] Storage system -- [x] Event system -- [x] Error handling -- [ ] Plugin lifecycle hooks - -### Phase 5: Migration & Testing 🚧 -- [ ] Convert existing features to plugins -- [ ] Create plugin testing utilities -- [ ] Add plugin documentation -- [ ] Create example plugins - -### Phase 6: Future Enhancements 📝 -- [ ] Plugin dependencies system -- [ ] Plugin hot-reloading -- [ ] External plugin support -- [ ] Plugin marketplace infrastructure - -## Plugin Example - -```typescript -const timetablePlugin = { - id: 'timetable', - name: 'Timetable Enhancer', - description: 'Adds extra features to the timetable view', - version: '1.0.0', - settings: { - showWeekends: { - type: 'boolean', - default: false, - description: 'Show weekend days in the timetable' - }, - theme: { - type: 'select', - options: ['light', 'dark', 'auto'], - default: 'auto', - description: 'Timetable theme' - } - }, - - run: async (api) => { - // Listen for timetable mount - api.seqta.onMount('.timetable-view', (element) => { - // Get React access since we need to modify state - const fiber = api.seqta.getFiber('.timetable-view'); - - // Apply settings - if (api.settings.showWeekends) { - fiber.setState(prevState => ({ - ...prevState, - showWeekends: true - })); - } - }); - - // Watch for settings changes - api.settings.onChange('theme', async (newTheme) => { - const timetable = api.seqta.getFiber('.timetable-view'); - if (newTheme !== 'auto') { - await timetable.setProp('theme', newTheme); - } - }); - } -}; -``` - -## Directory Structure -``` -src/ - plugins/ - core/ - types.ts # Core type definitions - createAPI.ts # API implementation - manager.ts # Plugin manager - built-in/ # Built-in plugins - timetable/ - assessments/ - etc... -``` - -## API Type Definitions - -```typescript -interface BSAPI { - seqta: { - onMount: (selector: string, callback: (fiber: ReactFiber) => void) => void; - getFiber: (selector: string) => ReactFiber; - getCurrentPage: () => string; - onPageChange: (callback: (page: string) => void) => void; - }; - - settings: TSettings & { - onChange: ( - key: K, - callback: (value: TSettings[K]) => void - ) => void; - }; - - storage: { - get: (key: string) => Promise; - set: (key: string, value: any) => Promise; - }; - - events: { - on: (event: string, callback: (...args: any[]) => void) => void; - emit: (event: string, ...args: any[]) => void; - }; -} -``` \ No newline at end of file diff --git a/src/interface/components/store/Backgrounds.svelte b/src/interface/components/store/Backgrounds.svelte index 09650525..307af84a 100644 --- a/src/interface/components/store/Backgrounds.svelte +++ b/src/interface/components/store/Backgrounds.svelte @@ -1,10 +1,12 @@ diff --git a/src/interface/components/themes/ThemeSelector.svelte b/src/interface/components/themes/ThemeSelector.svelte index f68e0105..88e983e6 100644 --- a/src/interface/components/themes/ThemeSelector.svelte +++ b/src/interface/components/themes/ThemeSelector.svelte @@ -1,16 +1,13 @@