diff --git a/src/taskpane/components/App.tsx b/src/taskpane/components/App.tsx index 6887a506..27c39695 100644 --- a/src/taskpane/components/App.tsx +++ b/src/taskpane/components/App.tsx @@ -7,14 +7,17 @@ import ProtectedRoutes from '../../utils/ProtectedRoutes'; import { CitationStoreProvider } from '../contexts/CitationStoreContext'; import { CiteSupportProvider } from '../contexts/CiteSupportContext'; import Wrapper from './Wrapper'; +import { ThemeContextProvider } from '../contexts/ThemeContext'; +import { Theme } from '../../../types'; export interface AppProps { title: string; + theme: Theme; isOfficeInitialized: boolean; } function App(props: AppProps): ReactElement { - const { isOfficeInitialized, title } = props; + const { isOfficeInitialized, title, theme } = props; if (!isOfficeInitialized) { return ( @@ -23,20 +26,22 @@ function App(props: AppProps): ReactElement { } return ( - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + ); } export default App; diff --git a/src/taskpane/components/Footer.tsx b/src/taskpane/components/Footer.tsx index bc10bb4e..658d402a 100644 --- a/src/taskpane/components/Footer.tsx +++ b/src/taskpane/components/Footer.tsx @@ -1,7 +1,10 @@ import { Stack, ActionButton } from '@fluentui/react'; import React, { ReactElement } from 'react'; +import { Theme } from '../../../types'; import { + light, + dark, Signout, SyncBib, imageProps, @@ -13,9 +16,11 @@ import { interface FooterProps { onSyncBibliography: () => void; onLogout: () => void; + onThemeChange: () => void; + theme: Theme; } -function Footer({ onSyncBibliography, onLogout }: FooterProps): ReactElement { +function Footer({ onSyncBibliography, onLogout, onThemeChange, theme }: FooterProps): ReactElement { return ( jabref logo + void; +} + +const ThemeContext = createContext(null); + +const getTheme = (theme: Theme) => (theme === Theme.DARK ? darkTheme : lightTheme); + +export function ThemeContextProvider({ children, initTheme }: ThemeContextProps): JSX.Element { + const [theme, setThemeValue] = React.useState(initTheme); + const changeTheme = () => { + setThemeValue((prevVal) => { + const newVal = prevVal === Theme.DARK ? Theme.LIGHT : Theme.DARK; + UserPreferences.setTheme(newVal); + UserPreferences.syncPreferences(); + return newVal; + }); + }; + const value = { theme, changeTheme }; + return ( + + {children} + + ); +} + +export const useTheme = (): ThemeContextInterface => { + const context = React.useContext(ThemeContext); + if (!context) { + throw new Error( + 'useTheme must be used within a ThemeContextProvider. Wrap a parent component in to fix this error.' + ); + } + return context; +}; + +export default ThemeContext; diff --git a/src/taskpane/index.tsx b/src/taskpane/index.tsx index a1fcc2e9..4313d0fe 100644 --- a/src/taskpane/index.tsx +++ b/src/taskpane/index.tsx @@ -14,11 +14,13 @@ import { initializeIcons, ThemeProvider } from '@fluentui/react'; import { HashRouter as Router } from 'react-router-dom'; import App from './components/App'; import client from '../plugins/apollo/apolloClient'; +import { Theme } from '../../types'; +import UserPreferences from '../utils/UserPreferences'; initializeIcons(); +let theme: Theme; let isOfficeInitialized = false; - const title = 'JabRef Task Pane Add-in'; const render = (Component) => { @@ -27,7 +29,7 @@ const render = (Component) => { - + @@ -40,6 +42,7 @@ const render = (Component) => { // eslint-disable-next-line no-void void Office.onReady(() => { isOfficeInitialized = true; + theme = UserPreferences.getTheme(); render(App); }); diff --git a/src/taskpane/layout/Layout.tsx b/src/taskpane/layout/Layout.tsx index 190ac154..6d9cffa8 100644 --- a/src/taskpane/layout/Layout.tsx +++ b/src/taskpane/layout/Layout.tsx @@ -7,6 +7,7 @@ import { pivotStyle, scrollableStack } from './Layout.style'; import { useCiteSupport } from '../contexts/CiteSupportContext'; import { useLogoutMutation } from '../../generated/graphql'; import client from '../../plugins/apollo/apolloClient'; +import { useTheme } from '../contexts/ThemeContext'; type pivotItem = 'citationStyle' | 'dashboard'; @@ -15,6 +16,8 @@ const getTabId = (itemKey: string) => { }; function Layout(): JSX.Element { + const { theme, changeTheme } = useTheme(); + const [selectedKey, setSelectedKey] = useState('dashboard'); const handleLinkClick = (item?: PivotItem) => { @@ -51,7 +54,12 @@ function Layout(): JSX.Element { {selectedKey === 'dashboard' ? : } -