Files
BetterSEQTA-Plus/plugins.md
T
2025-03-18 07:52:16 +11:00

5.2 KiB

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:

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:

// 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:

// 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

  • Create basic plugin type definitions
  • Implement plugin manager
  • Set up basic API structure
  • Create plugin loading system

Phase 2: Settings System

  • Design settings storage structure
  • Implement settings proxy system
  • Add settings change notifications
  • Create settings validation

Phase 3: SEQTA Integration

  • Implement component mount detection
  • Create ReactFiber wrapper
  • Add page change detection
  • Create component state utilities

Phase 4: Plugin API Features

  • Storage system
  • Event system
  • 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

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

interface BSAPI<TSettings> {
  seqta: {
    onMount: (selector: string, callback: (fiber: ReactFiber) => void) => void;
    getFiber: (selector: string) => ReactFiber;
    getCurrentPage: () => string;
    onPageChange: (callback: (page: string) => void) => void;
  };

  settings: TSettings & {
    onChange: <K extends keyof TSettings>(
      key: K, 
      callback: (value: TSettings[K]) => void
    ) => void;
  };

  storage: {
    get: (key: string) => Promise<any>;
    set: (key: string, value: any) => Promise<void>;
  };

  events: {
    on: (event: string, callback: (...args: any[]) => void) => void;
    emit: (event: string, ...args: any[]) => void;
  };
}