From 346f49fa6608c16d2b482ee9fee8f2485526d112 Mon Sep 17 00:00:00 2001 From: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:35:20 -0700 Subject: [PATCH] Chore: Improve types for mobile and desktop `themeStyle` (#10297) --- .../app-desktop/gui/ClipperConfigScreen.tsx | 7 +- .../controls/MissingPasswordHelpLink.tsx | 6 +- .../EncryptionConfigScreen.tsx | 3 +- packages/app-desktop/gui/ExtensionBadge.tsx | 5 +- .../gui/KeymapConfig/styles/index.ts | 5 +- .../app-desktop/gui/MainScreen/MainScreen.tsx | 4 +- packages/app-desktop/gui/MultiNoteActions.tsx | 6 +- .../NoteBody/TinyMCE/styles/index.ts | 5 +- .../gui/NoteEditor/NoteTitle/NoteTitleBar.tsx | 3 +- .../gui/NoteEditor/styles/index.ts | 5 +- .../app-desktop/gui/NotePropertiesDialog.tsx | 2 +- .../gui/NoteToolbar/NoteToolbar.tsx | 5 +- packages/app-desktop/gui/ShareNoteDialog.tsx | 3 +- packages/app-desktop/gui/Sidebar/Sidebar.tsx | 13 +- .../gui/ToggleEditorsButton/styles/index.ts | 5 +- .../gui/ToolbarButton/styles/index.ts | 8 +- .../components/SelectDateTimeDialog.tsx | 2 +- packages/app-mobile/components/TextInput.tsx | 4 +- .../app-mobile/components/global-style.ts | 111 ++-- .../screens/ConfigScreen/SettingComponent.tsx | 2 +- .../components/screens/encryption-config.tsx | 3 +- .../components/side-menu-content.tsx | 5 +- packages/editor/types.ts | 2 +- .../lib/services/style/themeToCss.test.ts | 7 + packages/lib/theme.ts | 554 +++++++++--------- packages/lib/themes/dark.ts | 3 + packages/lib/themes/light.ts | 4 + packages/lib/themes/type.ts | 4 + 28 files changed, 408 insertions(+), 378 deletions(-) diff --git a/packages/app-desktop/gui/ClipperConfigScreen.tsx b/packages/app-desktop/gui/ClipperConfigScreen.tsx index efefe8235..6fd1dfa36 100644 --- a/packages/app-desktop/gui/ClipperConfigScreen.tsx +++ b/packages/app-desktop/gui/ClipperConfigScreen.tsx @@ -1,4 +1,5 @@ const React = require('react'); +import { CSSProperties } from 'react'; const { connect } = require('react-redux'); const { clipboard } = require('electron'); import ExtensionBadge from './ExtensionBadge'; @@ -46,7 +47,8 @@ class ClipperConfigScreenComponent extends React.Component { public render() { const theme = themeStyle(this.props.themeId); - const containerStyle = { ...theme.containerStyle, overflowY: 'scroll', + const containerStyle: CSSProperties = { ...theme.containerStyle, + overflowY: 'scroll', // padding: theme.configScreenPadding, backgroundColor: theme.backgroundColor3 }; @@ -104,7 +106,8 @@ class ClipperConfigScreenComponent extends React.Component { ); } - const apiTokenStyle = { ...theme.textStyle, color: theme.colorFaded, + const apiTokenStyle: CSSProperties = { ...theme.textStyle, + color: theme.colorFaded, wordBreak: 'break-all', paddingTop: 10, paddingBottom: 10 }; diff --git a/packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.tsx b/packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.tsx index 0cad75749..79ea17690 100644 --- a/packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.tsx +++ b/packages/app-desktop/gui/ConfigScreen/controls/MissingPasswordHelpLink.tsx @@ -3,10 +3,10 @@ import * as React from 'react'; import shim from '@joplin/lib/shim'; import bridge from '../../../services/bridge'; import StyledLink from '../../style/StyledLink'; +import { ThemeStyle } from '@joplin/lib/theme'; interface Props { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - theme: any; + theme: ThemeStyle; text: string; } @@ -19,7 +19,7 @@ const MacOSMissingPasswordHelpLink: React.FunctionComponent = props => { const macInfoLink = ( {props.text} diff --git a/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx b/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx index 2275f88f1..5f3f9c422 100644 --- a/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx +++ b/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx @@ -35,8 +35,7 @@ interface Props { const EncryptionConfigScreen = (props: Props) => { const { inputPasswords, onInputPasswordChange } = useInputPasswords(props.passwords); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const theme: any = useMemo(() => { + const theme = useMemo(() => { return themeStyle(props.themeId); }, [props.themeId]); diff --git a/packages/app-desktop/gui/ExtensionBadge.tsx b/packages/app-desktop/gui/ExtensionBadge.tsx index cf4a65d5c..440f54cd0 100644 --- a/packages/app-desktop/gui/ExtensionBadge.tsx +++ b/packages/app-desktop/gui/ExtensionBadge.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import bridge from '../services/bridge'; import { _ } from '@joplin/lib/locale'; -import { themeStyle } from '@joplin/lib/theme'; +import { ThemeStyle, themeStyle } from '@joplin/lib/theme'; const { createSelector } = require('reselect'); interface Props { @@ -17,8 +17,7 @@ const themeSelector = (_state: any, props: any) => themeStyle(props.themeId); const styleSelector = createSelector( themeSelector, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - (theme: any) => { + (theme: ThemeStyle) => { const output = { root: { width: 220, diff --git a/packages/app-desktop/gui/KeymapConfig/styles/index.ts b/packages/app-desktop/gui/KeymapConfig/styles/index.ts index 1470e7e26..1487cabd7 100644 --- a/packages/app-desktop/gui/KeymapConfig/styles/index.ts +++ b/packages/app-desktop/gui/KeymapConfig/styles/index.ts @@ -1,8 +1,9 @@ +import { ThemeStyle } from '@joplin/lib/theme'; + const { buildStyle } = require('@joplin/lib/theme'); export default function styles(themeId: number) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle('KeymapConfigScreen', themeId, (theme: any) => { + return buildStyle('KeymapConfigScreen', themeId, (theme: ThemeStyle) => { return { container: { ...theme.containerStyle, diff --git a/packages/app-desktop/gui/MainScreen/MainScreen.tsx b/packages/app-desktop/gui/MainScreen/MainScreen.tsx index 89a5acefb..399878699 100644 --- a/packages/app-desktop/gui/MainScreen/MainScreen.tsx +++ b/packages/app-desktop/gui/MainScreen/MainScreen.tsx @@ -26,7 +26,7 @@ import shim from '@joplin/lib/shim'; import bridge from '../../services/bridge'; import time from '@joplin/lib/time'; import styled from 'styled-components'; -import { themeStyle } from '@joplin/lib/theme'; +import { themeStyle, ThemeStyle } from '@joplin/lib/theme'; import validateLayout from '../ResizableLayout/utils/validateLayout'; import iterateItems from '../ResizableLayout/utils/iterateItems'; import removeItem from '../ResizableLayout/utils/removeItem'; @@ -572,7 +572,7 @@ class MainScreenComponent extends React.Component { } // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - public renderNotification(theme: any, styles: any) { + public renderNotification(theme: ThemeStyle, styles: any) { if (!this.messageBoxVisible()) return null; const onViewStatusScreen = () => { diff --git a/packages/app-desktop/gui/MultiNoteActions.tsx b/packages/app-desktop/gui/MultiNoteActions.tsx index fbe60a9b6..c97bdf0f3 100644 --- a/packages/app-desktop/gui/MultiNoteActions.tsx +++ b/packages/app-desktop/gui/MultiNoteActions.tsx @@ -2,8 +2,9 @@ import { PluginStates } from '@joplin/lib/services/plugins/reducer'; import * as React from 'react'; import NoteListUtils from './utils/NoteListUtils'; import { Dispatch } from 'redux'; +import { ThemeStyle } from '@joplin/lib/theme'; -const { buildStyle } = require('@joplin/lib/theme'); +import { buildStyle } from '@joplin/lib/theme'; const bridge = require('@electron/remote').require('./bridge').default; interface MultiNoteActionsProps { @@ -19,8 +20,7 @@ interface MultiNoteActionsProps { } function styles_(props: MultiNoteActionsProps) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle('MultiNoteActions', props.themeId, (theme: any) => { + return buildStyle('MultiNoteActions', props.themeId, (theme: ThemeStyle) => { return { root: { display: 'inline-flex', diff --git a/packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.ts b/packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.ts index 1dc8115b3..1ee07bb3b 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.ts +++ b/packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.ts @@ -1,11 +1,10 @@ import { ThemeAppearance } from '@joplin/lib/themes/type'; import { NoteBodyEditorProps } from '../../../utils/types'; -const { buildStyle } = require('@joplin/lib/theme'); +import { buildStyle } from '@joplin/lib/theme'; export default function styles(props: NoteBodyEditorProps) { const leftExtraToolbarContainerWidth = props.watchedNoteFiles.length > 0 ? 120 : 80; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle(['TinyMCE', props.style.width, props.style.height, leftExtraToolbarContainerWidth], props.themeId, (theme: any) => { + return buildStyle(['TinyMCE', props.style.width, props.style.height, leftExtraToolbarContainerWidth], props.themeId, theme => { const extraToolbarContainer = { boxSizing: 'content-box', backgroundColor: theme.backgroundColor3, diff --git a/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx b/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx index 95d4f9697..34b9cddac 100644 --- a/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx +++ b/packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx @@ -43,8 +43,7 @@ interface Props { } function styles_(props: Props) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle(['NoteEditorTitleBar'], props.themeId, (theme: any) => { + return buildStyle(['NoteEditorTitleBar'], props.themeId, theme => { return { titleInput: { flex: 1, diff --git a/packages/app-desktop/gui/NoteEditor/styles/index.ts b/packages/app-desktop/gui/NoteEditor/styles/index.ts index 70145c1ed..64331581e 100644 --- a/packages/app-desktop/gui/NoteEditor/styles/index.ts +++ b/packages/app-desktop/gui/NoteEditor/styles/index.ts @@ -1,10 +1,9 @@ import { NoteEditorProps } from '../utils/types'; -const { buildStyle } = require('@joplin/lib/theme'); +import { buildStyle } from '@joplin/lib/theme'; export default function styles(props: NoteEditorProps) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle(['NoteEditor'], props.themeId, (theme: any) => { + return buildStyle(['NoteEditor'], props.themeId, theme => { return { root: { boxSizing: 'border-box', diff --git a/packages/app-desktop/gui/NotePropertiesDialog.tsx b/packages/app-desktop/gui/NotePropertiesDialog.tsx index c25eee638..226dcd74f 100644 --- a/packages/app-desktop/gui/NotePropertiesDialog.tsx +++ b/packages/app-desktop/gui/NotePropertiesDialog.tsx @@ -353,7 +353,7 @@ class NotePropertiesDialog extends React.Component { const ll = this.latLongFromLocation(value); url = Note.geoLocationUrlFromLatLong(ll.latitude, ll.longitude); } - const urlStyle = { ...theme.urlStyle, maxWidth: '180px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }; + const urlStyle: React.CSSProperties = { ...theme.urlStyle, maxWidth: '180px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }; controlComp = ( bridge().openExternal(url)} style={urlStyle}> {displayedValue} diff --git a/packages/app-desktop/gui/NoteToolbar/NoteToolbar.tsx b/packages/app-desktop/gui/NoteToolbar/NoteToolbar.tsx index 46f1b26ef..07a8f006a 100644 --- a/packages/app-desktop/gui/NoteToolbar/NoteToolbar.tsx +++ b/packages/app-desktop/gui/NoteToolbar/NoteToolbar.tsx @@ -5,7 +5,7 @@ import { utils as pluginUtils } from '@joplin/lib/services/plugins/reducer'; import ToolbarButtonUtils, { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils'; import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext'; const { connect } = require('react-redux'); -const { buildStyle } = require('@joplin/lib/theme'); +import { buildStyle } from '@joplin/lib/theme'; interface NoteToolbarProps { themeId: number; @@ -16,8 +16,7 @@ interface NoteToolbarProps { } function styles_(props: NoteToolbarProps) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle('NoteToolbar', props.themeId, (theme: any) => { + return buildStyle('NoteToolbar', props.themeId, theme => { return { root: { ...props.style, diff --git a/packages/app-desktop/gui/ShareNoteDialog.tsx b/packages/app-desktop/gui/ShareNoteDialog.tsx index 36a029c03..b62b58f7a 100644 --- a/packages/app-desktop/gui/ShareNoteDialog.tsx +++ b/packages/app-desktop/gui/ShareNoteDialog.tsx @@ -28,8 +28,7 @@ interface Props { } function styles_(props: Props) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle('ShareNoteDialog', props.themeId, (theme: any) => { + return buildStyle('ShareNoteDialog', props.themeId, theme => { return { root: { minWidth: 500, diff --git a/packages/app-desktop/gui/Sidebar/Sidebar.tsx b/packages/app-desktop/gui/Sidebar/Sidebar.tsx index b05be2d65..9a7255f73 100644 --- a/packages/app-desktop/gui/Sidebar/Sidebar.tsx +++ b/packages/app-desktop/gui/Sidebar/Sidebar.tsx @@ -24,13 +24,12 @@ import PerFolderSortOrderService from '../../services/sortOrder/PerFolderSortOrd import { getFolderCallbackUrl, getTagCallbackUrl } from '@joplin/lib/callbackUrlUtils'; import FolderIconBox from '../FolderIconBox'; import onFolderDrop from '@joplin/lib/models/utils/onFolderDrop'; -import { Theme } from '@joplin/lib/themes/type'; import { RuntimeProps } from './commands/focusElementSideBar'; const { connect } = require('react-redux'); import { renderFolders, renderTags } from '@joplin/lib/components/shared/side-menu-shared'; import { getTrashFolderIcon, getTrashFolderId } from '@joplin/lib/services/trash'; import { focus } from '@joplin/lib/utils/focusHandler'; -const { themeStyle } = require('@joplin/lib/theme'); +import { ThemeStyle, themeStyle } from '@joplin/lib/theme'; const bridge = require('@electron/remote').require('./bridge').default; const Menu = bridge().Menu; const MenuItem = bridge().MenuItem; @@ -505,10 +504,10 @@ const SidebarComponent = (props: Props) => { return count ? {count} : null; }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const renderExpandIcon = (theme: any, isExpanded: boolean, isVisible: boolean) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const style: any = { width: 16, maxWidth: 16, opacity: 0.5, fontSize: Math.round(theme.toolbarIconSize * 0.8), display: 'flex', justifyContent: 'center' }; + const renderExpandIcon = (theme: ThemeStyle, isExpanded: boolean, isVisible: boolean) => { + const style: React.CSSProperties = { + width: 16, maxWidth: 16, opacity: 0.5, fontSize: Math.round(theme.toolbarIconSize * 0.8), display: 'flex', justifyContent: 'center', + }; if (!isVisible) style.visibility = 'hidden'; return ; }; @@ -527,7 +526,7 @@ const SidebarComponent = (props: Props) => { menu.popup({ window: bridge().window() }); }, []); - const renderAllNotesItem = (theme: Theme, selected: boolean) => { + const renderAllNotesItem = (theme: ThemeStyle, selected: boolean) => { return ( {renderExpandIcon(theme, false, false)} diff --git a/packages/app-desktop/gui/ToggleEditorsButton/styles/index.ts b/packages/app-desktop/gui/ToggleEditorsButton/styles/index.ts index a9aa8e981..319739ab6 100644 --- a/packages/app-desktop/gui/ToggleEditorsButton/styles/index.ts +++ b/packages/app-desktop/gui/ToggleEditorsButton/styles/index.ts @@ -1,9 +1,8 @@ import { Props, Value } from '../ToggleEditorsButton'; -const { buildStyle } = require('@joplin/lib/theme'); +import { buildStyle } from '@joplin/lib/theme'; export default function styles(props: Props) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - return buildStyle(['ToggleEditorsButton', props.value], props.themeId, (theme: any) => { + return buildStyle(['ToggleEditorsButton', props.value], props.themeId, theme => { const iconSize = 15; const mdIconWidth = iconSize * 1.25; const buttonHeight = theme.toolbarHeight - 7; diff --git a/packages/app-desktop/gui/ToolbarButton/styles/index.ts b/packages/app-desktop/gui/ToolbarButton/styles/index.ts index 00130e872..ec0f04184 100644 --- a/packages/app-desktop/gui/ToolbarButton/styles/index.ts +++ b/packages/app-desktop/gui/ToolbarButton/styles/index.ts @@ -1,9 +1,10 @@ +import { ThemeStyle } from '@joplin/lib/theme'; + const styled = require('styled-components').default; const { css } = require('styled-components'); interface RootProps { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - readonly theme: any; + readonly theme: ThemeStyle; readonly disabled: boolean; readonly hasTitle: boolean; } @@ -34,8 +35,7 @@ export const StyledRoot = styled.a` `; interface IconProps { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - readonly theme: any; + readonly theme: ThemeStyle; readonly title: string; } diff --git a/packages/app-mobile/components/SelectDateTimeDialog.tsx b/packages/app-mobile/components/SelectDateTimeDialog.tsx index 55c8b4cd0..dfef3945f 100644 --- a/packages/app-mobile/components/SelectDateTimeDialog.tsx +++ b/packages/app-mobile/components/SelectDateTimeDialog.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { themeStyle } from '@joplin/lib/theme'; +import { themeStyle } from './global-style'; import { _ } from '@joplin/lib/locale'; const { Modal, View, Button, Text, StyleSheet } = require('react-native'); import time from '@joplin/lib/time'; diff --git a/packages/app-mobile/components/TextInput.tsx b/packages/app-mobile/components/TextInput.tsx index fac6deeb1..f0fac134d 100644 --- a/packages/app-mobile/components/TextInput.tsx +++ b/packages/app-mobile/components/TextInput.tsx @@ -1,6 +1,6 @@ const React = require('react'); import { useMemo } from 'react'; -import { themeStyle } from '@joplin/lib/theme'; +import { themeStyle } from './global-style'; import { TextInput, TextInputProps, StyleSheet } from 'react-native'; interface Props extends TextInputProps { @@ -9,7 +9,7 @@ interface Props extends TextInputProps { export default (props: Props) => { const theme = themeStyle(props.themeId); - const finalProps = { ...props }; + const finalProps: Props = { ...props }; if (!('placeholderTextColor' in finalProps)) finalProps.placeholderTextColor = theme.colorFaded; if (!('underlineColorAndroid' in finalProps)) finalProps.underlineColorAndroid = theme.dividerColor; diff --git a/packages/app-mobile/components/global-style.ts b/packages/app-mobile/components/global-style.ts index f80254a3c..f77384dbd 100644 --- a/packages/app-mobile/components/global-style.ts +++ b/packages/app-mobile/components/global-style.ts @@ -1,6 +1,7 @@ -const Setting = require('@joplin/lib/models/Setting').default; -const { Platform } = require('react-native'); -const { themeById } = require('@joplin/lib/theme'); +import Setting from '@joplin/lib/models/Setting'; +import { Platform, TextStyle, ViewStyle } from 'react-native'; +import { themeById } from '@joplin/lib/theme'; +import { Theme as BaseTheme } from '@joplin/lib/themes/type'; const baseStyle = { appearance: 'light', @@ -14,74 +15,95 @@ const baseStyle = { lineHeight: '1.6em', }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -const themeCache_: any = {}; +export type ThemeStyle = BaseTheme & typeof baseStyle & { + fontSize: number; + fontSizeSmaller: number; + marginRight: number; + marginLeft: number; + marginTop: number; + marginBottom: number; + icon: TextStyle; + lineInput: ViewStyle; + buttonRow: ViewStyle; + normalText: TextStyle; + urlText: TextStyle; + headerStyle: TextStyle; + headerWrapperStyle: ViewStyle; + keyboardAppearance: 'light'|'dark'; +}; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -function addExtraStyles(style: any) { - style.marginRight = style.margin; - style.marginLeft = style.margin; - style.marginTop = style.margin; - style.marginBottom = style.margin; +const themeCache_: Record = {}; - style.icon = { - color: style.color, +function extraStyles(theme: BaseTheme) { + const icon: TextStyle = { + color: theme.color, fontSize: 30, }; - style.lineInput = { - color: style.color, - backgroundColor: style.backgroundColor, + const lineInput: TextStyle = { + color: theme.color, + backgroundColor: theme.backgroundColor, borderBottomWidth: 1, - borderColor: style.dividerColor, + borderColor: theme.dividerColor, paddingBottom: 0, }; if (Platform.OS === 'ios') { - delete style.lineInput.borderBottomWidth; - delete style.lineInput.borderColor; + delete lineInput.borderBottomWidth; + delete lineInput.borderColor; } - style.buttonRow = { + const buttonRow: ViewStyle = { flexDirection: 'row', borderTopWidth: 1, - borderTopColor: style.dividerColor, + borderTopColor: theme.dividerColor, paddingTop: 10, }; - style.normalText = { - color: style.color, - fontSize: style.fontSize, + const fontSize = baseStyle.fontSize; + const normalText: TextStyle = { + color: theme.color, + fontSize: fontSize, }; - style.urlText = { - color: style.urlColor, - fontSize: style.fontSize, + const urlText: TextStyle = { + color: theme.urlColor, + fontSize, }; - style.headerStyle = { - color: style.color, - fontSize: style.fontSize * 1.2, + const headerStyle: TextStyle = { + color: theme.color, + fontSize: fontSize * 1.2, fontWeight: 'bold', }; - style.headerWrapperStyle = { - backgroundColor: style.headerBackgroundColor, + const headerWrapperStyle: TextStyle = { + backgroundColor: theme.headerBackgroundColor, }; - style.keyboardAppearance = style.appearance; + return { + marginRight: baseStyle.margin, + marginLeft: baseStyle.margin, + marginTop: baseStyle.margin, + marginBottom: baseStyle.margin, - style.color5 = style.backgroundColor4; - style.backgroundColor5 = style.color4; + icon, + lineInput, + buttonRow, + normalText, + urlText, + headerStyle, + headerWrapperStyle, - return style; + keyboardAppearance: theme.appearance, + color5: theme.color5 ?? theme.backgroundColor4, + backgroundColor5: theme.backgroundColor5 ?? theme.color4, + }; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -function editorFont(fontId: any) { +function editorFont(fontId: number) { // IMPORTANT: The font mapping must match the one in Setting.js - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const fonts: any = { + const fonts: Record = { [Setting.FONT_DEFAULT]: null, [Setting.FONT_MENLO]: 'Menlo', [Setting.FONT_COURIER_NEW]: 'Courier New', @@ -104,8 +126,13 @@ function themeStyle(theme: number) { const cacheKey = [theme].join('-'); if (themeCache_[cacheKey]) return themeCache_[cacheKey]; - const output = { ...baseStyle, ...themeById(theme) }; - themeCache_[cacheKey] = addExtraStyles(output); + const baseTheme = themeById(theme); + const output: ThemeStyle = { + ...baseStyle, + ...baseTheme, + ...extraStyles(baseTheme), + }; + themeCache_[cacheKey] = output; return themeCache_[cacheKey]; } diff --git a/packages/app-mobile/components/screens/ConfigScreen/SettingComponent.tsx b/packages/app-mobile/components/screens/ConfigScreen/SettingComponent.tsx index 503d20f9a..b4b0f4b6e 100644 --- a/packages/app-mobile/components/screens/ConfigScreen/SettingComponent.tsx +++ b/packages/app-mobile/components/screens/ConfigScreen/SettingComponent.tsx @@ -135,7 +135,7 @@ const SettingComponent: React.FunctionComponent = props => { autoCorrect={false} autoComplete="off" selectionColor={theme.textSelectionColor} - keyboardAppearance={theme.settingKeyboardAppearance} + keyboardAppearance={theme.keyboardAppearance} autoCapitalize="none" key="control" style={styleSheet.settingControl} diff --git a/packages/app-mobile/components/screens/encryption-config.tsx b/packages/app-mobile/components/screens/encryption-config.tsx index b34873634..153cca50f 100644 --- a/packages/app-mobile/components/screens/encryption-config.tsx +++ b/packages/app-mobile/components/screens/encryption-config.tsx @@ -41,8 +41,7 @@ const EncryptionConfigScreen = (props: Props) => { const nonExistingMasterKeyIds = props.notLoadedMasterKeys.slice(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const theme: any = useMemo(() => { + const theme = useMemo(() => { return themeStyle(props.themeId); }, [props.themeId]); diff --git a/packages/app-mobile/components/side-menu-content.tsx b/packages/app-mobile/components/side-menu-content.tsx index 9788b65ab..3031fbc0d 100644 --- a/packages/app-mobile/components/side-menu-content.tsx +++ b/packages/app-mobile/components/side-menu-content.tsx @@ -7,7 +7,7 @@ import Folder from '@joplin/lib/models/Folder'; import Synchronizer from '@joplin/lib/Synchronizer'; import NavService from '@joplin/lib/services/NavService'; import { _ } from '@joplin/lib/locale'; -import { themeStyle } from './global-style'; +import { ThemeStyle, themeStyle } from './global-style'; import { renderFolders } from '@joplin/lib/components/shared/side-menu-shared'; import { FolderEntity, FolderIcon, FolderIconType } from '@joplin/lib/services/database/types'; import { AppState } from '../utils/types'; @@ -376,8 +376,7 @@ const SideMenuContentComponent = (props: Props) => { if (actionDone === 'auth') props.dispatch({ type: 'SIDE_MENU_CLOSE' }); }, [performSync, props.dispatch]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const renderFolderIcon = (folderId: string, theme: any, folderIcon: FolderIcon) => { + const renderFolderIcon = (folderId: string, theme: ThemeStyle, folderIcon: FolderIcon) => { if (!folderIcon) { if (folderId === getTrashFolderId()) { folderIcon = getTrashFolderIcon(FolderIconType.Emoji); diff --git a/packages/editor/types.ts b/packages/editor/types.ts index fb021eb43..befc7cee7 100644 --- a/packages/editor/types.ts +++ b/packages/editor/types.ts @@ -126,7 +126,7 @@ export enum EditorKeymap { export interface EditorTheme extends Theme { fontFamily: string; fontSize?: number; - fontSizeUnits?: number; + fontSizeUnits?: string; isDesktop?: boolean; monospaceFont?: string; contentMaxWidth?: number; diff --git a/packages/lib/services/style/themeToCss.test.ts b/packages/lib/services/style/themeToCss.test.ts index c8de30b3d..cd176b834 100644 --- a/packages/lib/services/style/themeToCss.test.ts +++ b/packages/lib/services/style/themeToCss.test.ts @@ -55,6 +55,10 @@ const input: Theme = { codeMirrorTheme: 'default', codeThemeCss: 'atom-one-light.css', + + headerBackgroundColor: '#ffffff', + textSelectionColor: '#a0a0ff', + colorBright2: '#ffffff', }; const expected = ` @@ -76,6 +80,7 @@ const expected = ` --joplin-color2: #ffffff; --joplin-color3: #738598; --joplin-color4: #2D6BDC; + --joplin-color-bright2: #ffffff; --joplin-color-correct: green; --joplin-color-error: red; --joplin-color-error2: #ff6c6c; @@ -85,6 +90,7 @@ const expected = ` --joplin-color-warn3: #ff7626; --joplin-color-warn-url: #155BDA; --joplin-divider-color: #dddddd; + --joplin-header-background-color: #ffffff; --joplin-odd-background-color: #eeeeee; --joplin-raised-background-color: #e5e5e5; --joplin-raised-color: #222222; @@ -93,6 +99,7 @@ const expected = ` --joplin-selected-color: #e5e5e5; --joplin-selected-color2: #131313; --joplin-table-background-color: rgb(247, 247, 247); + --joplin-text-selection-color: #a0a0ff; --joplin-url-color: #155BDA; --joplin-warning-background-color: #FFD08D; }`; diff --git a/packages/lib/theme.ts b/packages/lib/theme.ts index 1dfd6598b..f3b8986e5 100644 --- a/packages/lib/theme.ts +++ b/packages/lib/theme.ts @@ -7,11 +7,11 @@ import theme_nord from './themes/nord'; import theme_aritimDark from './themes/aritimDark'; import theme_oledDark from './themes/oledDark'; import Setting from './models/Setting'; +import { Theme, ThemeAppearance } from './themes/type'; const Color = require('color'); -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -const themes: any = { +const themes: Record = { [Setting.THEME_LIGHT]: theme_light, [Setting.THEME_DARK]: theme_dark, [Setting.THEME_DRACULA]: theme_dracula, @@ -22,340 +22,330 @@ const themes: any = { [Setting.THEME_OLED_DARK]: theme_oledDark, }; -export function themeById(themeId: string) { +export function themeById(themeId: number) { if (!themes[themeId]) throw new Error(`Invalid theme ID: ${themeId}`); - const output = { ...themes[themeId] }; - - if (!output.headerBackgroundColor) { - output.headerBackgroundColor = output.appearance === 'light' ? '#F0F0F0' : '#2D3136'; - } - - if (!output.textSelectionColor) { - output.textSelectionColor = output.appearance === 'light' ? '#0096FF' : '#00AEFF'; - } - - if (!output.colorBright2) { - output.colorBright2 = output.appearance === 'light' ? '#ffffff' : '#ffffff'; - } - - return output; + return { ...themes[themeId] }; } +const literal = (str: T): T => str; + // globalStyle should be used for properties that do not change across themes // i.e. should not be used for colors -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -const globalStyle: any = { - fontFamily: 'Roboto', // 'sans-serif', - margin: 15, // No text and no interactive component should be within this margin - itemMarginTop: 10, - itemMarginBottom: 10, - disabledOpacity: 0.3, - buttonMinWidth: 50, - buttonMinHeight: 30, - editorFontSize: 12, - textAreaLineHeight: 17, - lineHeight: '1.6em', - headerButtonHPadding: 6, - toolbarHeight: 26, - toolbarPadding: 6, - appearance: 'light', - mainPadding: 12, - topRowHeight: 50, - editorPaddingLeft: 8, -}; +const globalStyle = (() => { -globalStyle.marginRight = globalStyle.margin; -globalStyle.marginLeft = globalStyle.margin; -globalStyle.marginTop = globalStyle.margin; -globalStyle.marginBottom = globalStyle.margin; + const margin = 15; // No text and no interactive component should be within this margin + const fontFamily = 'Roboto'; // 'sans-serif', + return { + fontFamily: fontFamily, + itemMarginTop: 10, + itemMarginBottom: 10, + disabledOpacity: 0.3, + buttonMinWidth: 50, + buttonMinHeight: 30, + editorFontSize: 12, + textAreaLineHeight: 17, + lineHeight: '1.6em', + headerButtonHPadding: 6, + toolbarHeight: 26, + toolbarPadding: 6, + appearance: ThemeAppearance.Light, + mainPadding: 12, + topRowHeight: 50, + editorPaddingLeft: 8, -globalStyle.icon = { - fontSize: 30, -}; + margin: margin, + marginRight: margin, + marginLeft: margin, + marginTop: margin, + marginBottom: margin, -globalStyle.lineInput = { - fontFamily: globalStyle.fontFamily, - maxHeight: 22, - height: 22, - paddingLeft: 5, -}; + icon: { fontSize: 30 }, + lineInput: { + fontFamily, + maxHeight: 22, + height: 22, + paddingLeft: 5, + }, + headerStyle: { + fontFamily, + }, + inputStyle: { + border: '1px solid', + height: 24, + maxHeight: 24, + paddingLeft: 5, + paddingRight: 5, + boxSizing: literal('border-box'), + }, + containerStyle: { + overflow: literal('auto'), + overflowY: literal('auto'), + }, + buttonStyle: { + // marginRight: 10, + border: '1px solid', + minHeight: 26, + minWidth: 80, + // maxWidth: 220, + paddingLeft: 12, + paddingRight: 12, + paddingTop: 6, + paddingBottom: 6, + // boxShadow: '0px 1px 1px rgba(0,0,0,0.3)', + borderRadius: 4, + }, + }; +})(); -globalStyle.headerStyle = { - fontFamily: globalStyle.fontFamily, -}; - -globalStyle.inputStyle = { - border: '1px solid', - height: 24, - maxHeight: 24, - paddingLeft: 5, - paddingRight: 5, - boxSizing: 'border-box', -}; - -globalStyle.containerStyle = { - overflow: 'auto', - overflowY: 'auto', -}; - -globalStyle.buttonStyle = { - // marginRight: 10, - border: '1px solid', - minHeight: 26, - minWidth: 80, - // maxWidth: 220, - paddingLeft: 12, - paddingRight: 12, - paddingTop: 6, - paddingBottom: 6, - // boxShadow: '0px 1px 1px rgba(0,0,0,0.3)', - fontSize: globalStyle.fontSize, - borderRadius: 4, -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -export function addExtraStyles(style: any) { +export function extraStyles(theme: Theme) { const zoomRatio = 1; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const fontSizes: any = { - fontSize: Math.round(12 * zoomRatio), + const baseFontSize = Math.round(12 * zoomRatio); + const fontSizes = { + fontSize: baseFontSize, toolbarIconSize: 18, + noteViewerFontSize: Math.round(baseFontSize * 1.25), }; - fontSizes.noteViewerFontSize = Math.round(fontSizes.fontSize * 1.25); + const bgColor4 = theme.backgroundColor4; + const borderColor4: string = Color(theme.color).alpha(0.3); + const iconColor = Color(theme.color).alpha(0.8); - style.zoomRatio = zoomRatio; + const backgroundColor5 = theme.backgroundColor5 ?? theme.color4; + const backgroundColorHover5 = Color(backgroundColor5).darken(0.2).hex(); + const backgroundColorActive5 = Color(backgroundColor5).darken(0.4).hex(); - style = { ...fontSizes, ...style }; - - style.selectedDividerColor = Color(style.dividerColor).darken(0.2).hex(); - style.iconColor = Color(style.color).alpha(0.8); - - style.colorFaded2 = Color(style.color2).alpha(0.5).rgb(); - style.colorHover2 = Color(style.color2).alpha(0.7).rgb(); - style.colorActive2 = Color(style.color2).alpha(0.9).rgb(); - - style.backgroundColorHoverDim3 = Color(style.backgroundColorHover3).alpha(0.3).rgb(); - style.backgroundColorActive3 = Color(style.backgroundColorHover3).alpha(0.5).rgb(); - - const bgColor4 = style.backgroundColor4; - - style.backgroundColorHover2 = Color(style.selectedColor2).alpha(0.4).rgb(); - - style.backgroundColorHover4 = Color(style.backgroundColorHover3).alpha(0.3).rgb(); - style.backgroundColorActive4 = Color(style.backgroundColorHover3).alpha(0.8).rgb(); - style.borderColor4 = Color(style.color).alpha(0.3); - style.backgroundColor4 = bgColor4; - - style.color5 = bgColor4; - style.backgroundColor5 = style.color4; - style.backgroundColorHover5 = Color(style.backgroundColor5).darken(0.2).hex(); - style.backgroundColorActive5 = Color(style.backgroundColor5).darken(0.4).hex(); - - style.configScreenPadding = style.mainPadding * 2; - - style.noteListHeaderHeight = 26; - style.noteListHeaderBorderPadding = 4; - - style.icon = { - ...style.icon, - color: style.color, + const inputStyle = { + ...globalStyle.inputStyle, + color: theme.color, + backgroundColor: theme.backgroundColor, + borderColor: theme.dividerColor, }; - style.lineInput = { - ...style.lineInput, - color: style.color, - backgroundColor: style.backgroundColor, + const containerStyle = { + ...globalStyle.containerStyle, + color: theme.color, + backgroundColor: theme.backgroundColor, }; - style.headerStyle = { - ...style.headerStyle, - color: style.color, - backgroundColor: style.backgroundColor, - }; - - style.inputStyle = { - ...style.inputStyle, - color: style.color, - backgroundColor: style.backgroundColor, - borderColor: style.dividerColor, - }; - - style.containerStyle = { - ...style.containerStyle, - color: style.color, - backgroundColor: style.backgroundColor, - }; - - style.buttonStyle = { - ...style.buttonStyle, - color: style.color4, - backgroundColor: style.backgroundColor4, - borderColor: style.borderColor4, - userSelect: 'none', + const buttonStyle = { + ...globalStyle.buttonStyle, + color: theme.color4, + backgroundColor: theme.backgroundColor4, + borderColor: borderColor4, + userSelect: literal('none'), // cursor: 'pointer', }; - style.tagStyle = { - fontSize: style.fontSize, - fontFamily: style.fontFamily, + const tagStyle = { + fontSize: baseFontSize, + fontFamily: globalStyle.fontFamily, paddingTop: 4, paddingBottom: 4, paddingRight: 10, paddingLeft: 10, - backgroundColor: style.backgroundColor3, - color: style.color3, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', + backgroundColor: theme.backgroundColor3, + color: theme.color3, + display: literal('flex'), + alignItems: literal('center'), + justifyContent: literal('center'), marginRight: 8, borderRadius: 100, borderWidth: 0, }; - style.toolbarStyle = { - height: style.toolbarHeight, - minWidth: style.toolbarHeight, - display: 'flex', - alignItems: 'center', - paddingLeft: style.headerButtonHPadding, - paddingRight: style.headerButtonHPadding, - textDecoration: 'none', - fontFamily: style.fontFamily, - fontSize: style.fontSize, - boxSizing: 'border-box', - cursor: 'default', - justifyContent: 'center', - color: style.color, - whiteSpace: 'nowrap', - }; - - style.textStyle = { + const toolbarStyle = { + height: globalStyle.toolbarHeight, + minWidth: globalStyle.toolbarHeight, + display: literal('flex'), + alignItems: literal('center'), + paddingLeft: globalStyle.headerButtonHPadding, + paddingRight: globalStyle.headerButtonHPadding, + textDecoration: literal('none'), fontFamily: globalStyle.fontFamily, - fontSize: style.fontSize, + fontSize: baseFontSize, + boxSizing: literal('border-box'), + cursor: literal('default'), + justifyContent: literal('center'), + color: theme.color, + whiteSpace: literal('nowrap'), + }; + + const textStyle = { + fontFamily: globalStyle.fontFamily, + fontSize: baseFontSize, lineHeight: '1.6em', - color: style.color, + color: theme.color, }; - style.clickableTextStyle = { ...style.textStyle, userSelect: 'none' }; - - style.textStyle2 = { ...style.textStyle, - color: style.color2, + const textStyle2 = { + ...textStyle, + color: theme.color2, }; - style.textStyleMinor = { ...style.textStyle, - color: style.colorFaded, - fontSize: style.fontSize * 0.8, + const textStyleMinor = { ...textStyle, + color: theme.colorFaded, + fontSize: baseFontSize * 0.8, }; - style.urlStyle = { ...style.textStyle, - textDecoration: 'underline', - color: style.urlColor, + const urlStyle = { + ...textStyle, + textDecoration: literal('underline'), + color: theme.urlColor, }; - style.h1Style = { - ...style.textStyle, - color: style.color, - fontSize: style.textStyle.fontSize * 1.5, - fontWeight: 'bold', + const h1Style = { + ...textStyle, + color: theme.color, + fontSize: textStyle.fontSize * 1.5, + fontWeight: literal('bold'), }; - style.h2Style = { - ...style.textStyle, - color: style.color, - fontSize: style.textStyle.fontSize * 1.3, - fontWeight: 'bold', + const h2Style = { + ...textStyle, + color: theme.color, + fontSize: textStyle.fontSize * 1.3, + fontWeight: literal('bold'), }; - style.dialogModalLayer = { - zIndex: 9999, - display: 'flex', - position: 'absolute', - top: 0, - left: 0, - width: '100%', - height: '100%', - backgroundColor: 'rgba(0,0,0,0.6)', - alignItems: 'flex-start', - justifyContent: 'center', + return { + zoomRatio, + ...fontSizes, + selectedDividerColor: Color(theme.dividerColor).darken(0.2).hex(), + iconColor, + colorFaded2: Color(theme.color2).alpha(0.5).rgb(), + colorHover2: Color(theme.color2).alpha(0.7).rgb(), + colorActive2: Color(theme.color2).alpha(0.9).rgb(), + + backgroundColorHoverDim3: Color(theme.backgroundColorHover3).alpha(0.3).rgb(), + backgroundColorActive3: Color(theme.backgroundColorHover3).alpha(0.5).rgb(), + backgroundColorHover2: Color(theme.selectedColor2).alpha(0.4).rgb(), + backgroundColorHover4: Color(theme.backgroundColorHover3).alpha(0.3).rgb(), + backgroundColorActive4: Color(theme.backgroundColorHover3).alpha(0.8).rgb(), + colorHover3: theme.color3, + borderColor4, + backgroundColor4: bgColor4, + color5: theme.color5 ?? bgColor4, + backgroundColor5, + backgroundColorHover5, + backgroundColorActive5, + + icon: { + ...globalStyle.icon, + color: theme.color, + }, + lineInput: { + ...globalStyle.lineInput, + color: theme.color, + backgroundColor: theme.backgroundColor, + }, + + containerStyle, + configScreenPadding: globalStyle.mainPadding * 2, + noteListHeaderHeight: 26, + noteListHeaderBorderPadding: 4, + + textStyle, + textStyle2, + textStyleMinor, + clickableTextStyle: { ...textStyle, userSelect: literal('none') }, + headerStyle: { + ...globalStyle.headerStyle, + color: theme.color, + backgroundColor: theme.backgroundColor, + }, + h1Style, + h2Style, + urlStyle, + inputStyle, + + toolbarStyle, + tagStyle, + buttonStyle, + + dialogModalLayer: { + zIndex: 9999, + display: literal('flex'), + position: literal('absolute'), + top: 0, + left: 0, + width: '100%', + height: '100%', + backgroundColor: 'rgba(0,0,0,0.6)', + alignItems: literal('flex-start'), + justifyContent: literal('center'), + }, + + controlBox: { + marginBottom: '1em', + color: 'black', // This will apply for the calendar + display: literal('flex'), + flexDirection: literal('row'), + alignItems: literal('center'), + }, + controlBoxLabel: { + marginRight: '1em', + width: '10em', + display: literal('inline-block'), + fontWeight: literal('bold'), + }, + controlBoxValue: { + display: literal('inline-block'), + }, + + dialogBox: { + backgroundColor: theme.backgroundColor, + padding: 16, + boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', + marginTop: 20, + maxHeight: '80%', + display: literal('flex'), + flexDirection: literal('column'), + }, + buttonIconStyle: { + color: iconColor, + marginRight: 6, + }, + notificationBox: { + backgroundColor: theme.warningBackgroundColor, + display: literal('flex'), + alignItems: literal('center'), + padding: 10, + fontSize: baseFontSize, + }, + dialogTitle: { ...h1Style, marginBottom: '1.2em' }, + dropdownList: { ...inputStyle }, + colorHover: theme.color, + backgroundHover: `${theme.selectedColor2}44`, + // In general the highlighted color, used to highlight text or icons, should be the same as selectedColor2 + // but some times, depending on the theme, it might be too dark or too light, so it can be + // specified directly by the theme too. + highlightedColor: theme.highlightedColor ?? theme.selectedColor2, }; - - style.controlBox = { - marginBottom: '1em', - color: 'black', // This will apply for the calendar - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - }; - - style.controlBoxLabel = { - marginRight: '1em', - width: '10em', - display: 'inline-block', - fontWeight: 'bold', - }; - - style.controlBoxValue = { - display: 'inline-block', - }; - - style.dialogBox = { - backgroundColor: style.backgroundColor, - padding: 16, - boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', - marginTop: 20, - maxHeight: '80%', - display: 'flex', - flexDirection: 'column', - }; - - style.buttonIconStyle = { - color: style.iconColor, - marginRight: 6, - }; - - style.notificationBox = { - backgroundColor: style.warningBackgroundColor, - display: 'flex', - alignItems: 'center', - padding: 10, - fontSize: style.fontSize, - }; - - style.dialogTitle = { ...style.h1Style, marginBottom: '1.2em' }; - - style.dropdownList = { ...style.inputStyle }; - - style.colorHover = style.color; - style.backgroundHover = `${style.selectedColor2}44`; - - // In general the highlighted color, used to highlight text or icons, should be the same as selectedColor2 - // but some times, depending on the theme, it might be too dark or too light, so it can be - // specified directly by the theme too. - if (!style.highlightedColor) style.highlightedColor = style.selectedColor2; - - return style; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -const themeCache_: any = {}; +type ExtraStyles = ReturnType; +type GlobalStyle = typeof globalStyle; +export type ThemeStyle = Theme & ExtraStyles & GlobalStyle & { cacheKey: number }; -export function themeStyle(themeId: number) { +const themeCache_: Record = {}; + +export function themeStyle(themeId: number): ThemeStyle { if (!themeId) throw new Error('Theme must be specified'); const cacheKey = themeId; if (themeCache_[cacheKey]) return themeCache_[cacheKey]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - let output: any = {}; + const output: ThemeStyle = { + cacheKey, + ...globalStyle, + ...themes[themeId], - // All theme are based on the light style, and just override the - // relevant properties - output = { ...globalStyle, ...themes[themeId] }; - output = addExtraStyles(output); - output.cacheKey = cacheKey; + // All theme are based on the light style, and just override the + // relevant properties + ...extraStyles(themes[themeId]), + }; themeCache_[cacheKey] = output; return themeCache_[cacheKey]; @@ -370,8 +360,10 @@ const cachedStyles_: any = { // cacheKey must be a globally unique key, and must change whenever // the dependencies of the style change. If the style depends only // on the theme, a static string can be provided as a cache key. -// eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any -- Old code before rule was applied, Old code before rule was applied -export function buildStyle(cacheKey: any, themeId: number, callback: Function) { +// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Partially refactored code from before rule was applied +type BuildStyleCallback = (style: ThemeStyle)=> any; +// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code from before rule was applied +export function buildStyle(cacheKey: any, themeId: number, callback: BuildStyleCallback) { cacheKey = Array.isArray(cacheKey) ? cacheKey.join('_') : cacheKey; // We clear the cache whenever switching themes diff --git a/packages/lib/themes/dark.ts b/packages/lib/themes/dark.ts index 095483705..c76700af1 100644 --- a/packages/lib/themes/dark.ts +++ b/packages/lib/themes/dark.ts @@ -56,6 +56,9 @@ const theme: Theme = { codeMirrorTheme: 'material-darker', codeThemeCss: 'atom-one-dark-reasonable.css', + + headerBackgroundColor: '#2D3136', + textSelectionColor: '#00AEFF', }; export default theme; diff --git a/packages/lib/themes/light.ts b/packages/lib/themes/light.ts index ee3d8dc23..fe2d36b33 100644 --- a/packages/lib/themes/light.ts +++ b/packages/lib/themes/light.ts @@ -55,6 +55,10 @@ const theme: Theme = { codeMirrorTheme: 'default', codeThemeCss: 'atom-one-light.css', + + headerBackgroundColor: '#F0F0F0', + textSelectionColor: '#0096FF', + colorBright2: '#ffffff', }; export default theme; diff --git a/packages/lib/themes/type.ts b/packages/lib/themes/type.ts index 5f7c5643d..a734e80d5 100644 --- a/packages/lib/themes/type.ts +++ b/packages/lib/themes/type.ts @@ -62,4 +62,8 @@ export interface Theme { codeThemeCss: string; highlightedColor?: string; + + headerBackgroundColor: string; + textSelectionColor: string; + colorBright2: string; }