You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// let it be { "navigate": boolean; "navigated": boolean }
23
+
// 'navigate' handles whether page should change
24
+
// 'navigated' handles whether link should show that page was opened
25
+
}
26
+
27
+
this.page=to;
28
+
},
29
+
"states": {
30
+
"home" : {},
31
+
"library" : {},
32
+
"settings": { "tab": "plugins" },
33
+
// plugins can add their own fields
34
+
};
35
+
"setState": (key:string; value:object) {
36
+
// handle hooks
37
+
38
+
this.states[key] =value;
39
+
},
40
+
};
41
+
42
+
window.__KAEDE__.router=/* pass the non-reactive object, or properties */
43
+
```
44
+
45
+
and in the `layout.vue`:
46
+
47
+
```vue
48
+
<script setup lang="ts">
49
+
const router = useRouterStore();
50
+
</script>
51
+
52
+
<template>
53
+
<...>
54
+
<home-page v-if="router.page === 'home'" />
55
+
<... />
56
+
<custom-page v-else />
57
+
</...>
58
+
</template>
59
+
```
60
+
61
+
simple ass.
62
+
63
+
and!! to make custom layouts even easier to do, we can use a `<Teleport />` for each page
64
+
65
+
plugins will change some state for `<Teleport />` to mount a page component on the page change to somewhere
66
+
67
+
___
68
+
69
+
wait, but why am I using a global store? This can be implemented with a simple top-level state in the App.vue buh
70
+
</details>
71
+
7
72
## Extensions
8
73
9
74
<details>
@@ -18,10 +83,12 @@ Make a page that fetches extensions from some remote repository
18
83
19
84
That repository must include only moderated extensions. Moderation process should require extension's source code and, if differs from usual, a build manual. Every extension update must go through the moderation process. This is the only way to make custom extensions secure, I guess
20
85
21
-
Those extensions should be loaded once at application launch. Programming language must be a JavaScript. Any framework is ok, as long as it is capable running in a browser. Extensions need to be able to communicate with launcher
86
+
Those extensions should be loaded once at application launch. Programming language must be a JavaScript. Any framework is ok, as long as it is capable running in a browser. Extensions will be able to communicate with the launcher
22
87
23
88
### More
24
89
90
+
**Previous implementation details**
91
+
25
92
Any JS code can be dynamically fetched in runtime from somewhere and executed with the `new Function` constructor. Example (I implemented it in [one of my projects](https://github.com/notwindstone/tsuki)):
26
93
27
94
```ts
@@ -44,11 +111,71 @@ Unfortunately, if VSCode, Obsidian, Vencord and other apps can't implement a sec
44
111
45
112
Btw, Figma chose security over functionality with their `iframe` approach
46
113
47
-
// 19.09.2025 update
114
+
**Latest implementation details (19.09.2025)**
115
+
116
+
Microfrontends supremacy >.<
117
+
118
+
Using a Module Federation Runtime we can load any Vue component just like an ordinary component in the node tree. To make it possible for plugins to render components anywhere, a `<Teleport />` could be used. Module Federation Runtime also allows us to share dependencies, so the final extension budle size should be low.
119
+
120
+
For other JS frameworks, we can run them using the previous implementation: `new Function`.
121
+
122
+
Launcher should expose everything that it can through the `window.__KAEDE__`. Previously, communication was done using the `window.postMessage` function, but now I came up with the idea of exposing an array of functions for almost every action in app. That array can be changed by extensions, and then the launcher will execute every function listed in that array.
123
+
124
+
For example, see the next code:
125
+
126
+
```ts
127
+
/** Launcher */
128
+
window.postMessage("kaede-route-changed", /* some data */)
While it works, it doesn't look good to me. Adding a lot of window listeners can affect launcher's performance. If user has 20 extensions, that `handleKaedeMessages` function will fire on every new event 20 times, even if no one wanted to listen to that event.
for (consthookof window.__KAEDE__.hooks.onRouteChange.before) {
168
+
hook({ pathname });
169
+
}
170
+
});
171
+
```
172
+
173
+
Extensions are not needed to listen for window events anymore. Only specified actions will be triggered. Must be a perfect solution? Maybe. I'm not sure that this will work, because, well, launcher doesn't have the same scope as that extension code block where `window.__KAEDE__` was reassigned (?)
48
174
49
-
consider using runtime microfrontends. mounting components can be achieved using portals (react)/teleports (vue)
175
+
Update: it works, somehow. I tested it both ways: firstly, I made a Svelte plugin state change from the Launcher (in Vue), and then I made a Vue state change from the Svelte plugin.
50
176
51
-
plugin manifest should also contain a `customLoader: string | undefined` field
177
+
___
178
+
about security: what if i introduce a permission-based plugin system? plugins will be able to use only those things (`window.__TAURI__` object scopes, localStorage, WASM, .dll/.so, etc.) that user has allowed
0 commit comments