diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js index 5ad605fe54..4cb662aca0 100644 --- a/services/web/config/settings.defaults.js +++ b/services/web/config/settings.defaults.js @@ -996,6 +996,8 @@ module.exports = { sourceEditorCompletionSources: [], sourceEditorSymbolPalette: [], sourceEditorToolbarComponents: [], + sourceEditorToolbarEndButtons: [], + rootContextProviders: [], mainEditorLayoutModals: [], langFeedbackLinkingWidgets: [], labsExperiments: [], diff --git a/services/web/frontend/js/features/ide-react/context/react-context-root.tsx b/services/web/frontend/js/features/ide-react/context/react-context-root.tsx index 60041059e8..8e8f75c067 100644 --- a/services/web/frontend/js/features/ide-react/context/react-context-root.tsx +++ b/services/web/frontend/js/features/ide-react/context/react-context-root.tsx @@ -1,4 +1,4 @@ -import React, { FC, PropsWithChildren } from 'react' +import React, { ElementType, FC, PropsWithChildren } from 'react' import { ChatProvider } from '@/features/chat/context/chat-context' import { ConnectionProvider } from './connection-context' import { DetachCompileProvider } from '@/shared/context/detach-compile-context' @@ -30,6 +30,12 @@ import { UserFeaturesProvider } from '@/shared/context/user-features-context' import { UserSettingsProvider } from '@/shared/context/user-settings-context' import { IdeRedesignSwitcherProvider } from './ide-redesign-switcher-context' import { CommandRegistryProvider } from './command-registry-context' +import importOverleafModules from '../../../../macros/import-overleaf-module.macro' + +const rootContextProviders = importOverleafModules('rootContextProviders') as { + import: { default: ElementType } + path: string +}[] export const ReactContextRoot: FC< React.PropsWithChildren<{ @@ -71,6 +77,18 @@ export const ReactContextRoot: FC< ...providers, } + // Extract dynamic providers from modules + const dynamicProviders = rootContextProviders.map( + module => module.import.default + ) + + // Wrap children with all dynamic providers from outside to inside + const childrenWrappedWithDynamicProviders = + dynamicProviders.reduceRight( + (acc, Provider) => {acc}, + <>{children} + ) + return ( @@ -103,7 +121,9 @@ export const ReactContextRoot: FC< - {children} + { + childrenWrappedWithDynamicProviders + } diff --git a/services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx b/services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx index a6265ecc93..0b8b8caa31 100644 --- a/services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx +++ b/services/web/frontend/js/features/source-editor/components/codemirror-toolbar.tsx @@ -40,6 +40,10 @@ const sourceEditorToolbarComponents = importOverleafModules( 'sourceEditorToolbarComponents' ) as { import: { default: ElementType }; path: string }[] +const sourceEditorToolbarEndButtons = importOverleafModules( + 'sourceEditorToolbarEndButtons' +) as { import: { default: ElementType }; path: string }[] + export const CodeMirrorToolbar = () => { const view = useCodeMirrorViewContext() const panel = getPanel(view, createToolbarPanel) @@ -204,6 +208,11 @@ const Toolbar = memo(function Toolbar() { className="ol-cm-toolbar-button-group ol-cm-toolbar-end" ref={handleButtons} > + {sourceEditorToolbarEndButtons.map( + ({ import: { default: Component }, path }) => ( + + ) + )} diff --git a/services/web/frontend/js/shared/context/types/writefull-instance.ts b/services/web/frontend/js/shared/context/types/writefull-instance.ts index 01b65ffe3f..0fb871905e 100644 --- a/services/web/frontend/js/shared/context/types/writefull-instance.ts +++ b/services/web/frontend/js/shared/context/types/writefull-instance.ts @@ -7,7 +7,6 @@ export interface WritefullEvents { } export interface WritefullAPI { - init(): void addEventListener( name: eventName, callback: (detail: WritefullEvents[eventName]) => void