From b2bb0b3d5d80aca3bd0237c6da6f2284dda262e5 Mon Sep 17 00:00:00 2001 From: Annika Hannig Date: Mon, 25 Jul 2022 22:51:25 +0200 Subject: [PATCH] extension API --- pkg/http/theme.go | 2 +- ui/src/api.js | 52 ++++++++++++++++++++++++++++ ui/src/app/components/page/Layout.js | 14 ++++++-- ui/src/app/context/content.js | 9 +++-- ui/src/index.js | 6 ++++ 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 ui/src/api.js diff --git a/pkg/http/theme.go b/pkg/http/theme.go index d4ee514..bff3e4e 100644 --- a/pkg/http/theme.go +++ b/pkg/http/theme.go @@ -119,7 +119,7 @@ func (t *Theme) ScriptIncludes() string { for _, script := range t.Scripts() { hash := t.HashInclude(script) include := fmt.Sprintf( - "", + "", t.Config.BasePath, script, hash, ) includes = append(includes, include) diff --git a/ui/src/api.js b/ui/src/api.js new file mode 100644 index 0000000..cea5963 --- /dev/null +++ b/ui/src/api.js @@ -0,0 +1,52 @@ + +/** + * Alice public theming and extension API + */ + +const apiFunc = () => { + let subs = []; + let props = []; + + const apply = () => { + let called = false; + for (const sub of subs) { + for (const prop of props) { + sub(...prop); + called = true; + } + } + if (called) { + subs = []; + } + } + + const call = (...params) => { + props.push(params); + apply(); + }; + + const subscribe = (fn) => { + subs = [...subs, fn]; + apply(); + }; + + return ([ + call, subscribe + ]) +} + +export const apiCallback = () => { + const [call, subscribe] = apiFunc(); + const callback = (...args) => subscribe((fn) => fn(...args)); + return [call, callback]; +} + +export const [updateContent, updateContentApi] = apiFunc(); +export const [onLayoutReady, onLayoutReadyApi] = apiCallback(); + +const Api = { + updateContent, + onLayoutReady, +}; + +export default Api; diff --git a/ui/src/app/components/page/Layout.js b/ui/src/app/components/page/Layout.js index a60ea87..c3597e1 100644 --- a/ui/src/app/components/page/Layout.js +++ b/ui/src/app/components/page/Layout.js @@ -4,6 +4,12 @@ * and a content view in the middle. */ +import { useEffect, useRef } + from 'react'; + +import { onLayoutReadyApi } + from 'api'; + import Content from 'app/components/content/Content'; import Errors @@ -11,12 +17,16 @@ import Errors import NavigationSidebar from 'app/components/navigation/Sidebar'; - const Layout = ({children}) => { + const pageRef = useRef(); + + useEffect(() => { + onLayoutReadyApi(pageRef.current); + }, [pageRef]); // Main Layout return ( -
+
diff --git a/ui/src/app/context/content.js b/ui/src/app/context/content.js index 8c42642..c2e9b47 100644 --- a/ui/src/app/context/content.js +++ b/ui/src/app/context/content.js @@ -5,6 +5,8 @@ import { useState } from 'react'; +import { updateContentApi } from 'api'; + export const ContentContext = createContext({}); export const useContent = () => useContext(ContentContext); @@ -12,12 +14,9 @@ export const useContent = () => useContext(ContentContext); export const ContentProvider = ({children}) => { const [content, setContent] = useState({}); - // Expose setContent as API?? useEffect(() => { - if (!window.API) { - window.API = {}; - } - window.API.setContent = setContent; + // Expose setContent in API + updateContentApi(setContent); }, [setContent]); return ( diff --git a/ui/src/index.js b/ui/src/index.js index 3c1fbc6..98080c2 100644 --- a/ui/src/index.js +++ b/ui/src/index.js @@ -11,6 +11,12 @@ import './scss/main.scss'; import Main from './app/Main'; +import Api + from './api' + +// Alice theme and extension API +window.Alice = Api; + const root = createRoot(document.getElementById('app')); root.render(
);