You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Chore: Improve types for mobile and desktop themeStyle (#10297)
				
					
				
			This commit is contained in:
		| @@ -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 }; | ||||
|   | ||||
| @@ -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> = props => { | ||||
| 	const macInfoLink = ( | ||||
| 		<StyledLink href="#" | ||||
| 			onClick={openMissingPasswordFAQ} | ||||
| 			style={props.theme.linkStyle} | ||||
| 			style={props.theme.urlStyle} | ||||
| 		> | ||||
| 			{props.text} | ||||
| 		</StyledLink> | ||||
|   | ||||
| @@ -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]); | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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<Props, State> { | ||||
| 	} | ||||
|  | ||||
| 	// 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 = () => { | ||||
|   | ||||
| @@ -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', | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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', | ||||
|   | ||||
| @@ -353,7 +353,7 @@ class NotePropertiesDialog extends React.Component<Props, State> { | ||||
| 					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 = ( | ||||
| 					<a href="#" onClick={() => bridge().openExternal(url)} style={urlStyle}> | ||||
| 						{displayedValue} | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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 ? <StyledNoteCount className="note-count-label">{count}</StyledNoteCount> : 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 <i className={isExpanded ? 'fas fa-caret-down' : 'fas fa-caret-right'} style={style}></i>; | ||||
| 	}; | ||||
| @@ -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 ( | ||||
| 			<StyledListItem key="allNotesHeader" selected={selected} className={'list-item-container list-item-depth-0 all-notes'} isSpecialItem={true}> | ||||
| 				<StyledExpandLink>{renderExpandIcon(theme, false, false)}</StyledExpandLink> | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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<RootProps>` | ||||
| `; | ||||
|  | ||||
| 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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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'; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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<string, ThemeStyle> = {}; | ||||
|  | ||||
| 	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<number, string|null> = { | ||||
| 		[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]; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -135,7 +135,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => { | ||||
| 						autoCorrect={false} | ||||
| 						autoComplete="off" | ||||
| 						selectionColor={theme.textSelectionColor} | ||||
| 						keyboardAppearance={theme.settingKeyboardAppearance} | ||||
| 						keyboardAppearance={theme.keyboardAppearance} | ||||
| 						autoCapitalize="none" | ||||
| 						key="control" | ||||
| 						style={styleSheet.settingControl} | ||||
|   | ||||
| @@ -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]); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
| }`; | ||||
|   | ||||
| @@ -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<number, Theme> = { | ||||
| 	[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 = <T extends string> (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<typeof extraStyles>; | ||||
| type GlobalStyle = typeof globalStyle; | ||||
| export type ThemeStyle = Theme & ExtraStyles & GlobalStyle & { cacheKey: number }; | ||||
|  | ||||
| export function themeStyle(themeId: number) { | ||||
| const themeCache_: Record<string, ThemeStyle> = {}; | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -56,6 +56,9 @@ const theme: Theme = { | ||||
|  | ||||
| 	codeMirrorTheme: 'material-darker', | ||||
| 	codeThemeCss: 'atom-one-dark-reasonable.css', | ||||
|  | ||||
| 	headerBackgroundColor: '#2D3136', | ||||
| 	textSelectionColor: '#00AEFF', | ||||
| }; | ||||
|  | ||||
| export default theme; | ||||
|   | ||||
| @@ -55,6 +55,10 @@ const theme: Theme = { | ||||
|  | ||||
| 	codeMirrorTheme: 'default', | ||||
| 	codeThemeCss: 'atom-one-light.css', | ||||
|  | ||||
| 	headerBackgroundColor: '#F0F0F0', | ||||
| 	textSelectionColor: '#0096FF', | ||||
| 	colorBright2: '#ffffff', | ||||
| }; | ||||
|  | ||||
| export default theme; | ||||
|   | ||||
| @@ -62,4 +62,8 @@ export interface Theme { | ||||
| 	codeThemeCss: string; | ||||
|  | ||||
| 	highlightedColor?: string; | ||||
|  | ||||
| 	headerBackgroundColor: string; | ||||
| 	textSelectionColor: string; | ||||
| 	colorBright2: string; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user