Update display settings, add advanced settings
This commit is contained in:
@ -84,7 +84,7 @@ const App = () => {
|
||||
margin={window.margin}
|
||||
maxWidthPercentage={window.maxWidthPercentage}
|
||||
lineHeight={window.lineHeight}
|
||||
highContrastFont={window.prefersHighContrastFont ?? true}
|
||||
highContrastText={window.prefersHighContrastFont ?? true}
|
||||
articleMutations={{
|
||||
createHighlightMutation: (input) =>
|
||||
mutation('createHighlight', input),
|
||||
|
||||
@ -19,6 +19,7 @@ import { LabelChip } from '../../elements/LabelChip'
|
||||
import { Label } from '../../../lib/networking/fragments/labelFragment'
|
||||
import { Recommendation } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
|
||||
import { Avatar } from '../../elements/Avatar'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
|
||||
type ArticleContainerProps = {
|
||||
article: ArticleAttributes
|
||||
@ -32,8 +33,9 @@ type ArticleContainerProps = {
|
||||
fontFamily?: string
|
||||
lineHeight?: number
|
||||
maxWidthPercentage?: number
|
||||
highContrastFont?: boolean
|
||||
highContrastText?: boolean
|
||||
showHighlightsModal: boolean
|
||||
justifyText?: boolean
|
||||
setShowHighlightsModal: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
@ -116,8 +118,8 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
||||
const [fontFamilyOverride, setFontFamilyOverride] = useState<string | null>(
|
||||
null
|
||||
)
|
||||
const [highContrastFont, setHighContrastFont] = useState(
|
||||
props.highContrastFont ?? false
|
||||
const [highContrastText, setHighContrastText] = useState(
|
||||
props.highContrastText ?? false
|
||||
)
|
||||
const highlightHref = useRef(
|
||||
window.location.hash ? window.location.hash.split('#')[1] : null
|
||||
@ -175,7 +177,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
||||
|
||||
const handleFontContrastChange = async (event: UpdateFontContrastEvent) => {
|
||||
const highContrast = event.fontContrast == 'high'
|
||||
setHighContrastFont(highContrast)
|
||||
setHighContrastText(highContrast)
|
||||
}
|
||||
|
||||
interface UpdateFontSizeEvent extends Event {
|
||||
@ -257,7 +259,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
||||
maxWidthPercentage: maxWidthPercentageOverride ?? props.maxWidthPercentage,
|
||||
lineHeight: lineHeightOverride ?? props.lineHeight ?? 150,
|
||||
fontFamily: fontFamilyOverride ?? props.fontFamily ?? 'inter',
|
||||
readerFontColor: highContrastFont
|
||||
readerFontColor: highContrastText
|
||||
? theme.colors.readerFontHighContrast.toString()
|
||||
: theme.colors.readerFont.toString(),
|
||||
readerTableHeaderColor: theme.colors.readerTableHeader.toString(),
|
||||
@ -283,6 +285,9 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
||||
background: props.isAppleAppEmbed
|
||||
? 'unset'
|
||||
: theme.colors.readerBg.toString(),
|
||||
'.article-inner-css': {
|
||||
textAlign: props.justifyText ? 'justify' : 'start',
|
||||
},
|
||||
'--text-font-family': styles.fontFamily,
|
||||
'--text-font-size': `${styles.fontSize}px`,
|
||||
'--line-height': `${styles.lineHeight}%`,
|
||||
|
||||
@ -17,11 +17,6 @@ type DisplaySettingsModalProps = {
|
||||
export function DisplaySettingsModal(
|
||||
props: DisplaySettingsModalProps
|
||||
): JSX.Element {
|
||||
const top =
|
||||
props.triggerElementRef?.current?.getBoundingClientRect().bottom ?? 0
|
||||
const left =
|
||||
props.triggerElementRef?.current?.getBoundingClientRect().left ?? 0
|
||||
|
||||
return (
|
||||
<ModalRoot defaultOpen onOpenChange={props.onOpenChange}>
|
||||
<ModalOverlay />
|
||||
|
||||
@ -2,7 +2,13 @@ import { HStack, VStack, SpanBox } from '../../elements/LayoutPrimitives'
|
||||
import { Button } from '../../elements/Button'
|
||||
import { StyledText } from '../../elements/StyledText'
|
||||
import { styled, theme, ThemeId } from '../../tokens/stitches.config'
|
||||
import { ArrowsHorizontal, ArrowsInLineHorizontal, Check } from 'phosphor-react'
|
||||
import {
|
||||
ArrowsHorizontal,
|
||||
ArrowsInLineHorizontal,
|
||||
CaretLeft,
|
||||
CaretRight,
|
||||
Check,
|
||||
} from 'phosphor-react'
|
||||
import { TickedRangeSlider } from '../../elements/TickedRangeSlider'
|
||||
import { showSuccessToast } from '../../../lib/toastHelpers'
|
||||
import { ReaderSettings } from '../../../lib/hooks/useReaderSettings'
|
||||
@ -10,6 +16,8 @@ import { useCallback, useMemo, useState } from 'react'
|
||||
import { currentThemeName, updateTheme } from '../../../lib/themeUpdater'
|
||||
import { LineHeightIncreaseIcon } from '../../elements/images/LineHeightIncreaseIconProps'
|
||||
import { LineHeightDecreaseIcon } from '../../elements/images/LineHeightDecreaseIcon'
|
||||
import * as Switch from '@radix-ui/react-switch'
|
||||
import { usePersistedState } from '../../../lib/hooks/usePersistedState'
|
||||
|
||||
type ReaderSettingsProps = {
|
||||
readerSettings: ReaderSettings
|
||||
@ -33,7 +41,158 @@ const FONT_FAMILIES = [
|
||||
'Source Serif Pro',
|
||||
]
|
||||
|
||||
type SettingsProps = {
|
||||
readerSettings: ReaderSettings
|
||||
setShowAdvanced: (show: boolean) => void
|
||||
}
|
||||
|
||||
export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element {
|
||||
const [showAdvanced, setShowAdvanced] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
{showAdvanced ? (
|
||||
<AdvancedSettings
|
||||
readerSettings={props.readerSettings}
|
||||
setShowAdvanced={setShowAdvanced}
|
||||
/>
|
||||
) : (
|
||||
<BasicSettings
|
||||
readerSettings={props.readerSettings}
|
||||
setShowAdvanced={setShowAdvanced}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function AdvancedSettings(props: SettingsProps): JSX.Element {
|
||||
return (
|
||||
<VStack
|
||||
css={{ width: '100%', minHeight: '320px', p: '10px' }}
|
||||
alignment="start"
|
||||
distribution="start"
|
||||
>
|
||||
<Button
|
||||
style="plainIcon"
|
||||
css={{
|
||||
m: '10px',
|
||||
mb: '20px',
|
||||
display: 'flex',
|
||||
fontSize: '12px',
|
||||
fontWeight: '400',
|
||||
fontFamily: '$display',
|
||||
alignItems: 'center',
|
||||
borderRadius: '6px',
|
||||
gap: '5px',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
props.setShowAdvanced(false)
|
||||
}}
|
||||
>
|
||||
<CaretLeft size={12} color="#969696" weight="bold" />
|
||||
Back
|
||||
</Button>
|
||||
|
||||
<HStack
|
||||
css={{
|
||||
width: '100%',
|
||||
pr: '30px',
|
||||
alignItems: 'center',
|
||||
'&:hover': {
|
||||
opacity: 0.8,
|
||||
},
|
||||
'&[data-state="on"]': {
|
||||
bg: '$thBackground',
|
||||
},
|
||||
}}
|
||||
alignment="start"
|
||||
distribution="between"
|
||||
>
|
||||
<Label htmlFor="justify-text" css={{ width: '100%' }}>
|
||||
<StyledText style="displaySettingsLabel" css={{ pl: '20px' }}>
|
||||
Justify Text
|
||||
</StyledText>
|
||||
</Label>
|
||||
<SwitchRoot
|
||||
id="justify-text"
|
||||
checked={props.readerSettings.justifyText ?? false}
|
||||
onCheckedChange={(checked) => {
|
||||
props.readerSettings.setJustifyText(checked)
|
||||
}}
|
||||
>
|
||||
<SwitchThumb />
|
||||
</SwitchRoot>
|
||||
</HStack>
|
||||
|
||||
<HStack
|
||||
css={{
|
||||
width: '100%',
|
||||
pr: '30px',
|
||||
alignItems: 'center',
|
||||
'&:hover': {
|
||||
opacity: 0.8,
|
||||
},
|
||||
'&[data-state="on"]': {
|
||||
bg: '$thBackground',
|
||||
},
|
||||
}}
|
||||
alignment="start"
|
||||
distribution="between"
|
||||
>
|
||||
<Label htmlFor="high-contrast-text" css={{ width: '100%' }}>
|
||||
<StyledText style="displaySettingsLabel" css={{ pl: '20px' }}>
|
||||
High Contrast Text
|
||||
</StyledText>
|
||||
</Label>
|
||||
<SwitchRoot
|
||||
id="high-contrast-text"
|
||||
checked={props.readerSettings.highContrastText ?? false}
|
||||
onCheckedChange={(checked) => {
|
||||
props.readerSettings.setHighContrastText(checked)
|
||||
}}
|
||||
>
|
||||
<SwitchThumb />
|
||||
</SwitchRoot>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
}
|
||||
|
||||
const SwitchRoot = styled(Switch.Root, {
|
||||
all: 'unset',
|
||||
width: 42,
|
||||
height: 25,
|
||||
backgroundColor: '$thBorderColor',
|
||||
borderRadius: '9999px',
|
||||
position: 'relative',
|
||||
WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)',
|
||||
'&:focus': { boxShadow: `0 0 0 2px $thBorderColor` },
|
||||
'&[data-state="checked"]': { backgroundColor: '$thBorderColor' },
|
||||
})
|
||||
|
||||
const SwitchThumb = styled(Switch.Thumb, {
|
||||
display: 'block',
|
||||
width: 21,
|
||||
height: 21,
|
||||
backgroundColor: '$thTextContrast2',
|
||||
borderRadius: '9999px',
|
||||
transition: 'transform 100ms',
|
||||
transform: 'translateX(2px)',
|
||||
willChange: 'transform',
|
||||
'&[data-state="checked"]': { transform: 'translateX(19px)' },
|
||||
})
|
||||
|
||||
const Label = styled('label', {
|
||||
color: 'white',
|
||||
fontSize: 15,
|
||||
lineHeight: 1,
|
||||
})
|
||||
|
||||
function BasicSettings(props: SettingsProps): JSX.Element {
|
||||
return (
|
||||
<VStack css={{ width: '100%' }}>
|
||||
<FontControls readerSettings={props.readerSettings} />
|
||||
@ -48,11 +207,15 @@ export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element {
|
||||
|
||||
<HorizontalDivider />
|
||||
|
||||
<HStack distribution="start" css={{ width: '100%', p: '20px' }}>
|
||||
<HStack
|
||||
distribution="start"
|
||||
alignment="center"
|
||||
css={{ width: '100%', p: '10px' }}
|
||||
>
|
||||
<Button
|
||||
style="plainIcon"
|
||||
css={{
|
||||
p: '0px',
|
||||
pl: '10px',
|
||||
display: 'flex',
|
||||
fontSize: '12px',
|
||||
fontWeight: '600',
|
||||
@ -73,6 +236,29 @@ export function ReaderSettingsControl(props: ReaderSettingsProps): JSX.Element {
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
<Button
|
||||
style="plainIcon"
|
||||
css={{
|
||||
p: '5px',
|
||||
display: 'flex',
|
||||
fontSize: '12px',
|
||||
fontWeight: '400',
|
||||
fontFamily: '$display',
|
||||
marginLeft: 'auto',
|
||||
alignItems: 'center',
|
||||
borderRadius: '6px',
|
||||
gap: '5px',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
onClick={() => {
|
||||
props.setShowAdvanced(true)
|
||||
}}
|
||||
>
|
||||
Advanced Settings
|
||||
<CaretRight size={12} color="#969696" weight="bold" />
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
)
|
||||
|
||||
@ -33,10 +33,17 @@ export type ReaderSettings = {
|
||||
|
||||
fontFamily: string
|
||||
setFontFamily: (newStyle: string) => void
|
||||
|
||||
justifyText: boolean | undefined
|
||||
setJustifyText: (set: boolean) => void
|
||||
highContrastText: boolean | undefined
|
||||
setHighContrastText: (set: boolean) => void
|
||||
}
|
||||
|
||||
export const useReaderSettings = (): ReaderSettings => {
|
||||
const { preferencesData } = useGetUserPreferences()
|
||||
const [, updateState] = useState({})
|
||||
|
||||
const [fontSize, setFontSize] = usePersistedState({
|
||||
key: 'fontSize',
|
||||
initialValue: preferencesData?.fontSize ?? 20,
|
||||
@ -53,6 +60,17 @@ export const useReaderSettings = (): ReaderSettings => {
|
||||
key: 'fontFamily',
|
||||
initialValue: DEFAULT_FONT,
|
||||
})
|
||||
const [highContrastText, setHighContrastText] = usePersistedState<
|
||||
boolean | undefined
|
||||
>({
|
||||
key: `--display-high-contrast-text`,
|
||||
initialValue: false,
|
||||
})
|
||||
|
||||
const [justifyText, setJustifyText] = usePersistedState<boolean | undefined>({
|
||||
key: `--display-justify-text`,
|
||||
initialValue: false,
|
||||
})
|
||||
const [showSetLabelsModal, setShowSetLabelsModal] = useState(false)
|
||||
const [showEditDisplaySettingsModal, setShowEditDisplaySettingsModal] =
|
||||
useState(false)
|
||||
@ -65,6 +83,12 @@ export const useReaderSettings = (): ReaderSettings => {
|
||||
})()
|
||||
}
|
||||
|
||||
// const [hideMargins, setHideMargins] = usePersistedState<boolean | undefined>({
|
||||
// key: `--display-hide-margins`,
|
||||
// initialValue: false,
|
||||
// isSessionStorage: false,
|
||||
// })
|
||||
|
||||
const actionHandler = useCallback(
|
||||
(action: string, arg?: unknown) => {
|
||||
switch (action) {
|
||||
@ -199,5 +223,9 @@ export const useReaderSettings = (): ReaderSettings => {
|
||||
actionHandler,
|
||||
setFontFamily,
|
||||
fontFamily,
|
||||
justifyText,
|
||||
setJustifyText,
|
||||
highContrastText,
|
||||
setHighContrastText,
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,6 +376,8 @@ export default function Home(): JSX.Element {
|
||||
labels={labels}
|
||||
showHighlightsModal={showHighlightsModal}
|
||||
setShowHighlightsModal={setShowHighlightsModal}
|
||||
justifyText={readerSettings.justifyText ?? undefined}
|
||||
highContrastText={readerSettings.highContrastText ?? undefined}
|
||||
articleMutations={{
|
||||
createHighlightMutation,
|
||||
deleteHighlightMutation,
|
||||
@ -413,9 +415,9 @@ export default function Home(): JSX.Element {
|
||||
<DisplaySettingsModal
|
||||
centerX={true}
|
||||
readerSettings={readerSettings}
|
||||
onOpenChange={() =>
|
||||
onOpenChange={() => {
|
||||
readerSettings.setShowEditDisplaySettingsModal(false)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{readerSettings.showDeleteConfirmation && (
|
||||
|
||||
@ -324,7 +324,6 @@ on smaller screens we display the note icon
|
||||
}
|
||||
|
||||
.article-inner-css .page {
|
||||
text-align: start;
|
||||
word-wrap: break-word;
|
||||
|
||||
font-size: var(--text-font-size);
|
||||
|
||||
Reference in New Issue
Block a user