mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
format: run prettify
This commit is contained in:
+3
-1
@@ -7,11 +7,13 @@ Welcome to the BetterSEQTA+ documentation! This documentation will help you unde
|
||||
## Table of Contents
|
||||
|
||||
### Getting Started
|
||||
|
||||
- [Project Overview](./README.md) - This file
|
||||
- [Installation Guide](./installation.md) - How to install and set up BetterSEQTA+
|
||||
- [Contributing Guide](../CONTRIBUTING.md) - How to contribute to BetterSEQTA+
|
||||
|
||||
### Plugin System
|
||||
|
||||
- [Creating Your First Plugin](./plugins/README.md) - A comprehensive, beginner-friendly guide to creating plugins
|
||||
- [Plugin API Reference](./plugins/api-reference.md) - Detailed technical documentation of the plugin APIs
|
||||
|
||||
@@ -47,4 +49,4 @@ To contribute to the documentation:
|
||||
|
||||
## License
|
||||
|
||||
BetterSEQTA+ is licensed under the [MIT License](../LICENSE).
|
||||
BetterSEQTA+ is licensed under the [MIT License](../LICENSE).
|
||||
|
||||
@@ -22,6 +22,7 @@ Thank you for your interest in contributing to BetterSEQTA+! This document provi
|
||||
BetterSEQTA+ is committed to providing a welcoming and inclusive environment for all contributors. We expect all participants to adhere to our Code of Conduct, which promotes respectful and harassment-free interaction.
|
||||
|
||||
Key points:
|
||||
|
||||
- Be respectful and inclusive
|
||||
- Focus on what is best for the community
|
||||
- Show empathy towards other community members
|
||||
@@ -105,6 +106,7 @@ git checkout -b feature/my-new-feature
|
||||
2. **Write Clear Commit Messages**
|
||||
|
||||
Follow the conventional commits format:
|
||||
|
||||
```
|
||||
feat: add new feature
|
||||
fix: resolve bug with timetable
|
||||
@@ -118,6 +120,7 @@ git checkout -b feature/my-new-feature
|
||||
4. **Run Tests**
|
||||
|
||||
Make sure all tests pass before submitting your PR:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
@@ -157,6 +160,7 @@ We follow TypeScript best practices and have a consistent code style:
|
||||
5. **Use Linters**
|
||||
|
||||
We use ESLint and Prettier. Run them before submitting your PR:
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
npm run format
|
||||
@@ -173,6 +177,7 @@ If you find a bug, please report it by creating an issue on GitHub:
|
||||
2. **Use the Bug Report Template**
|
||||
|
||||
Fill in all sections of the bug report template:
|
||||
|
||||
- Description
|
||||
- Steps to reproduce
|
||||
- Expected behavior
|
||||
@@ -195,6 +200,7 @@ We welcome feature suggestions! To suggest a new feature:
|
||||
2. **Use the Feature Request Template**
|
||||
|
||||
Fill in all sections of the feature request template:
|
||||
|
||||
- Description
|
||||
- Use case
|
||||
- Potential implementation
|
||||
@@ -259,4 +265,4 @@ If you have any questions about contributing, please:
|
||||
2. Ask in the Discord server
|
||||
3. Open a GitHub Discussion
|
||||
|
||||
Thank you for contributing to BetterSEQTA+! Your efforts help make SEQTA better for students and teachers everywhere.
|
||||
Thank you for contributing to BetterSEQTA+! Your efforts help make SEQTA better for students and teachers everywhere.
|
||||
|
||||
@@ -132,6 +132,7 @@ bun install
|
||||
#### Extension not appearing in SEQTA
|
||||
|
||||
Make sure:
|
||||
|
||||
- You're visiting a SEQTA Learn page
|
||||
- The extension is enabled
|
||||
- You've refreshed the page after installing the extension
|
||||
@@ -139,6 +140,7 @@ Make sure:
|
||||
#### Development build not updating
|
||||
|
||||
Try:
|
||||
|
||||
1. Stopping the development server
|
||||
2. Clearing your browser cache
|
||||
3. Removing the extension from your browser
|
||||
@@ -177,4 +179,4 @@ bun run dev
|
||||
Now that you have BetterSEQTA+ installed, you can:
|
||||
|
||||
- [Getting Started with Plugins](./plugins/getting-started.md)
|
||||
- [Contribute to the project](../CONTRIBUTING.md)
|
||||
- [Contribute to the project](../CONTRIBUTING.md)
|
||||
|
||||
+52
-42
@@ -5,6 +5,7 @@ Hey there! 👋 So you want to create a plugin for BetterSEQTA+? That's awesome!
|
||||
## What is a Plugin?
|
||||
|
||||
In BetterSEQTA+, a plugin is like a mini-app that adds new features to SEQTA. Think of it as a piece of LEGO that you can snap onto SEQTA to make it do new things. For example, you could create a plugin that:
|
||||
|
||||
- Changes how SEQTA looks
|
||||
- Adds new buttons or features
|
||||
- Shows extra information on your timetable
|
||||
@@ -16,40 +17,40 @@ In BetterSEQTA+, a plugin is like a mini-app that adds new features to SEQTA. Th
|
||||
Let's create a super simple plugin together. We'll make one that adds a friendly message to the SEQTA homepage. Here's what we'll need:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
|
||||
const myFirstPlugin: Plugin = {
|
||||
// Every plugin needs these basic details
|
||||
id: 'my-first-plugin',
|
||||
name: 'My First Plugin',
|
||||
description: 'Adds a friendly message to SEQTA',
|
||||
version: '1.0.0',
|
||||
|
||||
id: "my-first-plugin",
|
||||
name: "My First Plugin",
|
||||
description: "Adds a friendly message to SEQTA",
|
||||
version: "1.0.0",
|
||||
|
||||
// This tells BetterSEQTA+ that users can turn our plugin on/off
|
||||
disableToggle: true,
|
||||
|
||||
// This is where the magic happens!
|
||||
|
||||
// This is where the magic happens!
|
||||
run: async (api) => {
|
||||
// Wait for the homepage to load
|
||||
api.seqta.onMount('.home-page', (homePage) => {
|
||||
api.seqta.onMount(".home-page", (homePage) => {
|
||||
// Create our message
|
||||
const message = document.createElement('div');
|
||||
message.textContent = 'Hello from my first plugin! 🎉';
|
||||
message.style.padding = '20px';
|
||||
message.style.backgroundColor = '#e9f5ff';
|
||||
message.style.borderRadius = '8px';
|
||||
message.style.margin = '20px';
|
||||
|
||||
const message = document.createElement("div");
|
||||
message.textContent = "Hello from my first plugin! 🎉";
|
||||
message.style.padding = "20px";
|
||||
message.style.backgroundColor = "#e9f5ff";
|
||||
message.style.borderRadius = "8px";
|
||||
message.style.margin = "20px";
|
||||
|
||||
// Add it to the page
|
||||
homePage.prepend(message);
|
||||
});
|
||||
|
||||
|
||||
// Return a cleanup function that removes our message when the plugin is disabled
|
||||
return () => {
|
||||
const message = document.querySelector('.home-page > div');
|
||||
const message = document.querySelector(".home-page > div");
|
||||
message?.remove();
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default myFirstPlugin;
|
||||
@@ -79,13 +80,13 @@ This helps you interact with SEQTA's pages:
|
||||
|
||||
```typescript
|
||||
// Wait for an element to appear on the page
|
||||
api.seqta.onMount('.some-class', (element) => {
|
||||
api.seqta.onMount(".some-class", (element) => {
|
||||
// Do something with the element
|
||||
});
|
||||
|
||||
// Know when the user changes pages
|
||||
api.seqta.onPageChange((page) => {
|
||||
console.log('User went to:', page);
|
||||
console.log("User went to:", page);
|
||||
});
|
||||
|
||||
// Get the current page
|
||||
@@ -97,8 +98,12 @@ const currentPage = api.seqta.getCurrentPage();
|
||||
Want to let users customize your plugin? Use settings!
|
||||
|
||||
```typescript
|
||||
import { BasePlugin } from '@/plugins/core/settings';
|
||||
import { booleanSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
|
||||
import { BasePlugin } from "@/plugins/core/settings";
|
||||
import {
|
||||
booleanSetting,
|
||||
defineSettings,
|
||||
Setting,
|
||||
} from "@/plugins/core/settingsHelpers";
|
||||
|
||||
// Define your settings
|
||||
const settings = defineSettings({
|
||||
@@ -106,7 +111,7 @@ const settings = defineSettings({
|
||||
default: true,
|
||||
title: "Show Welcome Message",
|
||||
description: "Show a friendly message on the homepage",
|
||||
})
|
||||
}),
|
||||
});
|
||||
|
||||
// Create a class for your plugin
|
||||
@@ -121,22 +126,22 @@ const settingsInstance = new MyPluginClass();
|
||||
const myPlugin: Plugin<typeof settings> = {
|
||||
// ... other plugin details ...
|
||||
settings: settingsInstance.settings,
|
||||
|
||||
|
||||
run: async (api) => {
|
||||
// Use the setting
|
||||
if (api.settings.showMessage) {
|
||||
// Show the message
|
||||
}
|
||||
|
||||
|
||||
// Listen for setting changes
|
||||
api.settings.onChange('showMessage', (newValue) => {
|
||||
api.settings.onChange("showMessage", (newValue) => {
|
||||
if (newValue) {
|
||||
// Show the message
|
||||
} else {
|
||||
// Hide the message
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -146,14 +151,14 @@ Need to save some data? The storage API has got you covered:
|
||||
|
||||
```typescript
|
||||
// Save some data
|
||||
await api.storage.set('lastVisit', new Date().toISOString());
|
||||
await api.storage.set("lastVisit", new Date().toISOString());
|
||||
|
||||
// Get it back later
|
||||
const lastVisit = await api.storage.get('lastVisit');
|
||||
const lastVisit = await api.storage.get("lastVisit");
|
||||
|
||||
// Listen for changes
|
||||
api.storage.onChange('lastVisit', (newValue) => {
|
||||
console.log('Last visit updated:', newValue);
|
||||
api.storage.onChange("lastVisit", (newValue) => {
|
||||
console.log("Last visit updated:", newValue);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -163,12 +168,12 @@ Want your plugin to be able to interface with other plugins? Then use events!
|
||||
|
||||
```typescript
|
||||
// Listen for an event
|
||||
api.events.on('myCustomEvent', (data) => {
|
||||
console.log('Got event:', data);
|
||||
api.events.on("myCustomEvent", (data) => {
|
||||
console.log("Got event:", data);
|
||||
});
|
||||
|
||||
// Send an event
|
||||
api.events.emit('myCustomEvent', { some: 'data' });
|
||||
api.events.emit("myCustomEvent", { some: "data" });
|
||||
```
|
||||
|
||||
## Adding Styles
|
||||
@@ -178,7 +183,7 @@ Want to make your plugin look pretty? You can add CSS styles:
|
||||
```typescript
|
||||
const myPlugin: Plugin = {
|
||||
// ... other plugin details ...
|
||||
|
||||
|
||||
// Add your CSS here
|
||||
styles: `
|
||||
.my-plugin-message {
|
||||
@@ -196,10 +201,10 @@ const myPlugin: Plugin = {
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
`,
|
||||
|
||||
|
||||
run: async (api) => {
|
||||
// Your plugin code here
|
||||
}
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -208,28 +213,31 @@ const myPlugin: Plugin = {
|
||||
Here are some tips to make your plugin awesome:
|
||||
|
||||
1. **Always Clean Up**: When your plugin is disabled, clean up any changes you made:
|
||||
|
||||
```typescript
|
||||
run: async (api) => {
|
||||
// Add stuff to the page
|
||||
const element = document.createElement('div');
|
||||
const element = document.createElement("div");
|
||||
document.body.appendChild(element);
|
||||
|
||||
|
||||
// Return a cleanup function
|
||||
return () => {
|
||||
element.remove();
|
||||
};
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
2. **Use TypeScript**: It helps catch errors before they happen and makes your code easier to understand.
|
||||
|
||||
3. **Test Your Plugin**: Make sure it works in different situations:
|
||||
|
||||
- When SEQTA is loading
|
||||
- When the user switches pages
|
||||
- When the plugin is enabled/disabled
|
||||
- When settings are changed
|
||||
|
||||
4. **Keep It Fast**: Don't slow down SEQTA:
|
||||
|
||||
- Use `onMount` instead of intervals or timeouts
|
||||
- Clean up event listeners when they're not needed
|
||||
- Don't do heavy calculations on the main thread
|
||||
@@ -242,6 +250,7 @@ Here are some tips to make your plugin awesome:
|
||||
## Examples
|
||||
|
||||
Want to see more examples? Check out our built-in plugins:
|
||||
|
||||
- [themes](../../src/plugins/built-in/themes/index.ts): Shows how to change SEQTA's appearance
|
||||
- [notificationCollector](../../src/plugins/built-in/notificationCollector/index.ts): Shows how to work with SEQTA's notifications
|
||||
- [timetable](../../src/plugins/built-in/timetable/index.ts): Shows how to modify SEQTA's timetable view
|
||||
@@ -250,8 +259,9 @@ Want to see more examples? Check out our built-in plugins:
|
||||
## Need Help?
|
||||
|
||||
Got stuck? No worries! Here's where you can get help:
|
||||
|
||||
- Join our [Discord server](https://discord.gg/YzmbnCDkat)
|
||||
- Check out the built-in plugins in the `src/plugins/built-in` folder
|
||||
- Open an issue on our [GitHub page](https://github.com/betterseqta/betterseqta-plus/issues)
|
||||
|
||||
Happy coding and feel free to checkout the api reference [here](./api-reference.md)
|
||||
Happy coding and feel free to checkout the api reference [here](./api-reference.md)
|
||||
|
||||
+100
-78
@@ -7,9 +7,13 @@ This document provides detailed technical information about BetterSEQTA+'s plugi
|
||||
Here's how a plugin is structured:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import { BasePlugin } from '@/plugins/core/settings';
|
||||
import { booleanSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
import { BasePlugin } from "@/plugins/core/settings";
|
||||
import {
|
||||
booleanSetting,
|
||||
defineSettings,
|
||||
Setting,
|
||||
} from "@/plugins/core/settingsHelpers";
|
||||
|
||||
// First, define your settings
|
||||
const settings = defineSettings({
|
||||
@@ -17,7 +21,7 @@ const settings = defineSettings({
|
||||
default: true,
|
||||
title: "Enable Feature",
|
||||
description: "Turn this feature on or off",
|
||||
})
|
||||
}),
|
||||
});
|
||||
|
||||
// Create a class to handle your settings
|
||||
@@ -31,28 +35,28 @@ const settingsInstance = new MyPluginClass();
|
||||
|
||||
// Create your plugin
|
||||
const myPlugin: Plugin<typeof settings> = {
|
||||
id: 'my-plugin',
|
||||
name: 'My Plugin',
|
||||
description: 'A cool plugin that does things',
|
||||
version: '1.0.0',
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "A cool plugin that does things",
|
||||
version: "1.0.0",
|
||||
settings: settingsInstance.settings,
|
||||
disableToggle: true,
|
||||
|
||||
run: async (api) => {
|
||||
console.log('Plugin is running!');
|
||||
|
||||
console.log("Plugin is running!");
|
||||
|
||||
// Do stuff when settings change
|
||||
api.settings.onChange('enabled', (enabled) => {
|
||||
api.settings.onChange("enabled", (enabled) => {
|
||||
if (enabled) {
|
||||
console.log('Feature enabled!');
|
||||
console.log("Feature enabled!");
|
||||
}
|
||||
});
|
||||
|
||||
// Return a cleanup function
|
||||
return () => {
|
||||
console.log('Plugin cleanup');
|
||||
console.log("Plugin cleanup");
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default myPlugin;
|
||||
@@ -63,27 +67,30 @@ export default myPlugin;
|
||||
The SEQTA API helps you interact with SEQTA's pages:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
|
||||
const seqtaPlugin: Plugin<typeof settings> = {
|
||||
id: 'seqta-example',
|
||||
name: 'SEQTA Example',
|
||||
description: 'Shows how to use the SEQTA API',
|
||||
version: '1.0.0',
|
||||
id: "seqta-example",
|
||||
name: "SEQTA Example",
|
||||
description: "Shows how to use the SEQTA API",
|
||||
version: "1.0.0",
|
||||
settings: {},
|
||||
disableToggle: true,
|
||||
|
||||
run: async (api) => {
|
||||
// Wait for elements to appear
|
||||
const { unregister: timetableUnregister } = api.seqta.onMount('.timetable', (timetable) => {
|
||||
const button = document.createElement('button');
|
||||
button.textContent = 'Export';
|
||||
timetable.appendChild(button);
|
||||
});
|
||||
const { unregister: timetableUnregister } = api.seqta.onMount(
|
||||
".timetable",
|
||||
(timetable) => {
|
||||
const button = document.createElement("button");
|
||||
button.textContent = "Export";
|
||||
timetable.appendChild(button);
|
||||
},
|
||||
);
|
||||
|
||||
// Track page changes
|
||||
const { unregister: pageUnregister } = api.seqta.onPageChange((page) => {
|
||||
console.log('User went to:', page);
|
||||
console.log("User went to:", page);
|
||||
});
|
||||
|
||||
// Clean up when disabled
|
||||
@@ -91,7 +98,7 @@ const seqtaPlugin: Plugin<typeof settings> = {
|
||||
timetableUnregister();
|
||||
pageUnregister();
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default seqtaPlugin;
|
||||
@@ -102,22 +109,29 @@ export default seqtaPlugin;
|
||||
Here's how to add settings to your plugin:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import { BasePlugin } from '@/plugins/core/settings';
|
||||
import { booleanSetting, stringSetting, numberSetting, selectSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
import { BasePlugin } from "@/plugins/core/settings";
|
||||
import {
|
||||
booleanSetting,
|
||||
stringSetting,
|
||||
numberSetting,
|
||||
selectSetting,
|
||||
defineSettings,
|
||||
Setting,
|
||||
} from "@/plugins/core/settingsHelpers";
|
||||
|
||||
// Define your settings
|
||||
const settings = defineSettings({
|
||||
darkMode: booleanSetting({
|
||||
default: false,
|
||||
title: "Dark Mode",
|
||||
description: "Enable dark mode"
|
||||
description: "Enable dark mode",
|
||||
}),
|
||||
userName: stringSetting({
|
||||
default: "",
|
||||
title: "User Name",
|
||||
description: "Your display name",
|
||||
placeholder: "Enter your name..."
|
||||
placeholder: "Enter your name...",
|
||||
}),
|
||||
theme: selectSetting({
|
||||
default: "light",
|
||||
@@ -125,9 +139,9 @@ const settings = defineSettings({
|
||||
description: "Choose your theme",
|
||||
options: [
|
||||
{ value: "light", label: "Light" },
|
||||
{ value: "dark", label: "Dark" }
|
||||
]
|
||||
})
|
||||
{ value: "dark", label: "Dark" },
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
// Create your settings class
|
||||
@@ -144,29 +158,29 @@ class ThemePluginClass extends BasePlugin<typeof settings> {
|
||||
|
||||
// Create the plugin
|
||||
const themePlugin: Plugin<typeof settings> = {
|
||||
id: 'theme-example',
|
||||
name: 'Theme Example',
|
||||
description: 'Shows how to use settings',
|
||||
version: '1.0.0',
|
||||
id: "theme-example",
|
||||
name: "Theme Example",
|
||||
description: "Shows how to use settings",
|
||||
version: "1.0.0",
|
||||
settings: new ThemePluginClass().settings,
|
||||
disableToggle: true,
|
||||
|
||||
run: async (api) => {
|
||||
// Apply initial settings
|
||||
if (api.settings.darkMode) {
|
||||
document.body.classList.add('dark');
|
||||
document.body.classList.add("dark");
|
||||
}
|
||||
|
||||
// Listen for changes
|
||||
const { unregister } = api.settings.onChange('darkMode', (enabled) => {
|
||||
document.body.classList.toggle('dark', enabled);
|
||||
const { unregister } = api.settings.onChange("darkMode", (enabled) => {
|
||||
document.body.classList.toggle("dark", enabled);
|
||||
});
|
||||
|
||||
return () => {
|
||||
unregister();
|
||||
document.body.classList.remove('dark');
|
||||
document.body.classList.remove("dark");
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default themePlugin;
|
||||
@@ -177,13 +191,13 @@ export default themePlugin;
|
||||
Here's how to use storage in your plugin:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
|
||||
const storagePlugin: Plugin<typeof settings> = {
|
||||
id: 'storage-example',
|
||||
name: 'Storage Example',
|
||||
description: 'Shows how to use storage',
|
||||
version: '1.0.0',
|
||||
id: "storage-example",
|
||||
name: "Storage Example",
|
||||
description: "Shows how to use storage",
|
||||
version: "1.0.0",
|
||||
settings: {},
|
||||
disableToggle: true,
|
||||
|
||||
@@ -192,21 +206,21 @@ const storagePlugin: Plugin<typeof settings> = {
|
||||
await api.storage.loaded;
|
||||
|
||||
// Save some data
|
||||
await api.storage.set('lastVisit', new Date().toISOString());
|
||||
|
||||
await api.storage.set("lastVisit", new Date().toISOString());
|
||||
|
||||
// Get saved data
|
||||
const lastVisit = await api.storage.get('lastVisit');
|
||||
console.log('Last visit:', lastVisit);
|
||||
const lastVisit = await api.storage.get("lastVisit");
|
||||
console.log("Last visit:", lastVisit);
|
||||
|
||||
// Listen for changes
|
||||
const { unregister } = api.storage.onChange('lastVisit', (newValue) => {
|
||||
console.log('Last visit updated:', newValue);
|
||||
const { unregister } = api.storage.onChange("lastVisit", (newValue) => {
|
||||
console.log("Last visit updated:", newValue);
|
||||
});
|
||||
|
||||
return () => {
|
||||
unregister();
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default storagePlugin;
|
||||
@@ -217,33 +231,39 @@ export default storagePlugin;
|
||||
Here's how to use events in your plugin:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
|
||||
const eventsPlugin: Plugin<typeof settings> = {
|
||||
id: 'events-example',
|
||||
name: 'Events Example',
|
||||
description: 'Shows how to use events',
|
||||
version: '1.0.0',
|
||||
id: "events-example",
|
||||
name: "Events Example",
|
||||
description: "Shows how to use events",
|
||||
version: "1.0.0",
|
||||
settings: {},
|
||||
disableToggle: true,
|
||||
|
||||
run: async (api) => {
|
||||
// Listen for theme changes
|
||||
const { unregister: themeListener } = api.events.on('theme.changed', (theme) => {
|
||||
console.log('Theme changed to:', theme);
|
||||
});
|
||||
const { unregister: themeListener } = api.events.on(
|
||||
"theme.changed",
|
||||
(theme) => {
|
||||
console.log("Theme changed to:", theme);
|
||||
},
|
||||
);
|
||||
|
||||
// Listen for notifications
|
||||
const { unregister: notifyListener } = api.events.on('notification.new', (notification) => {
|
||||
console.log('New notification:', notification);
|
||||
});
|
||||
const { unregister: notifyListener } = api.events.on(
|
||||
"notification.new",
|
||||
(notification) => {
|
||||
console.log("New notification:", notification);
|
||||
},
|
||||
);
|
||||
|
||||
// Clean up listeners
|
||||
return () => {
|
||||
themeListener();
|
||||
notifyListener();
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default eventsPlugin;
|
||||
@@ -254,20 +274,20 @@ export default eventsPlugin;
|
||||
Here's how to write efficient plugins:
|
||||
|
||||
```typescript
|
||||
import type { Plugin } from '@/plugins/core/types';
|
||||
import type { Plugin } from "@/plugins/core/types";
|
||||
|
||||
const efficientPlugin: Plugin<typeof settings> = {
|
||||
id: 'efficient-example',
|
||||
name: 'Efficient Example',
|
||||
description: 'Shows performance best practices',
|
||||
version: '1.0.0',
|
||||
id: "efficient-example",
|
||||
name: "Efficient Example",
|
||||
description: "Shows performance best practices",
|
||||
version: "1.0.0",
|
||||
settings: {},
|
||||
disableToggle: true,
|
||||
|
||||
run: async (api) => {
|
||||
// ✅ Good: Use onMount
|
||||
const { unregister } = api.seqta.onMount('.timetable', (el) => {
|
||||
el.classList.add('enhanced');
|
||||
const { unregister } = api.seqta.onMount(".timetable", (el) => {
|
||||
el.classList.add("enhanced");
|
||||
});
|
||||
|
||||
// ❌ Bad: Don't use intervals
|
||||
@@ -277,7 +297,7 @@ const efficientPlugin: Plugin<typeof settings> = {
|
||||
// }, 100);
|
||||
|
||||
// ✅ Good: Cache DOM elements
|
||||
const header = document.querySelector('.header');
|
||||
const header = document.querySelector(".header");
|
||||
if (header) {
|
||||
// Reuse header instead of querying again
|
||||
}
|
||||
@@ -285,7 +305,7 @@ const efficientPlugin: Plugin<typeof settings> = {
|
||||
// ✅ Good: Batch DOM updates
|
||||
const fragment = document.createDocumentFragment();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const div = document.createElement('div');
|
||||
const div = document.createElement("div");
|
||||
fragment.appendChild(div);
|
||||
}
|
||||
document.body.appendChild(fragment);
|
||||
@@ -294,13 +314,14 @@ const efficientPlugin: Plugin<typeof settings> = {
|
||||
unregister();
|
||||
// clearInterval(interval); // If you used the bad approach
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default efficientPlugin;
|
||||
```
|
||||
|
||||
Each plugin should be in its own file and exported as the default export. The plugin should:
|
||||
|
||||
1. Import necessary types and helpers
|
||||
2. Define settings if needed
|
||||
3. Create a settings class if using settings
|
||||
@@ -308,7 +329,8 @@ Each plugin should be in its own file and exported as the default export. The pl
|
||||
5. Export the plugin as default
|
||||
|
||||
Remember to always:
|
||||
|
||||
- Use proper TypeScript types
|
||||
- Clean up when your plugin is disabled
|
||||
- Handle errors gracefully
|
||||
- Follow the plugin structure shown above
|
||||
- Follow the plugin structure shown above
|
||||
|
||||
Reference in New Issue
Block a user