From 686ce5b504e40646a0d7b92114ef4f07f1f8992a Mon Sep 17 00:00:00 2001 From: Henry Bley-Vroman <bley.vroman@gmail.com> Date: Thu, 26 Sep 2024 19:31:01 -1000 Subject: [PATCH] Privacy mode: instead of blurring, use an illegible font (#3376) (#3377) * Privacy mode: instead of blurring, use an illegible font (#3376) * Privacy mode: no layout shift when switching mode * fix(Spending): update for latest PrivacyFilter * refactor(PrivacyFilter): use CSS :hover * chore(PrivacyFilter): no privacy mode BudgetCell height regression... https://github.com/actualbudget/actual/pull/3377?show_full=true#issuecomment-2357385371 * chore(GroupMonth): drop no-impact PrivacyFilter styles --- packages/desktop-client/package.json | 1 + .../src/components/PrivacyFilter.tsx | 86 ++++++++++++------- .../envelope/EnvelopeBudgetComponents.tsx | 10 --- .../envelope/budgetsummary/ToBudgetAmount.tsx | 6 +- .../tracking/TrackingBudgetComponents.tsx | 5 -- .../budget/tracking/budgetsummary/Saved.tsx | 4 +- .../src/components/reports/ReportSummary.tsx | 6 +- .../reports/reports/CustomReport.tsx | 2 +- .../components/reports/reports/NetWorth.jsx | 4 +- .../components/reports/reports/Spending.tsx | 8 +- .../desktop-client/src/components/table.tsx | 5 -- packages/desktop-client/src/fonts.scss | 2 + upcoming-release-notes/3377.md | 6 ++ yarn.lock | 8 ++ 14 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 upcoming-release-notes/3377.md diff --git a/packages/desktop-client/package.json b/packages/desktop-client/package.json index ffb902de6..b160ffc21 100644 --- a/packages/desktop-client/package.json +++ b/packages/desktop-client/package.json @@ -6,6 +6,7 @@ "build" ], "devDependencies": { + "@fontsource/redacted-script": "^5.0.21", "@juggle/resize-observer": "^3.4.0", "@playwright/test": "1.41.1", "@rollup/plugin-inject": "^5.0.5", diff --git a/packages/desktop-client/src/components/PrivacyFilter.tsx b/packages/desktop-client/src/components/PrivacyFilter.tsx index 5a455dc60..f8d832491 100644 --- a/packages/desktop-client/src/components/PrivacyFilter.tsx +++ b/packages/desktop-client/src/components/PrivacyFilter.tsx @@ -1,12 +1,12 @@ // @ts-strict-ignore import React, { - useState, - useCallback, Children, type ComponentPropsWithRef, type ReactNode, } from 'react'; +import { css } from 'glamor'; + import { usePrivacyMode } from '../hooks/usePrivacyMode'; import { useResponsive } from '../ResponsiveProvider'; @@ -44,11 +44,9 @@ export function ConditionalPrivacyFilter({ type PrivacyFilterProps = ComponentPropsWithRef<typeof View> & { activationFilters?: (boolean | (() => boolean))[]; - blurIntensity?: number; }; export function PrivacyFilter({ activationFilters, - blurIntensity, children, ...props }: PrivacyFilterProps) { @@ -63,46 +61,70 @@ export function PrivacyFilter({ typeof value === 'boolean' ? value : value(), )); - const blurAmount = blurIntensity != null ? `${blurIntensity}px` : '3px'; - return !activate ? ( <>{Children.toArray(children)}</> ) : ( - <BlurredOverlay blurIntensity={blurAmount} {...props}> - {children} - </BlurredOverlay> + <PrivacyOverlay {...props}>{children}</PrivacyOverlay> ); } -function BlurredOverlay({ blurIntensity, children, ...props }) { - const [hovered, setHovered] = useState(false); - const onHover = useCallback(() => setHovered(true), [setHovered]); - const onHoverEnd = useCallback(() => setHovered(false), [setHovered]); - - const blurStyle = { - ...(!hovered && { - filter: `blur(${blurIntensity})`, - WebkitFilter: `blur(${blurIntensity})`, - // To fix blur performance issue in Safari. - // https://graffino.com/til/CjT2jrcLHP-how-to-fix-filter-blur-performance-issue-in-safari - transform: `translate3d(0, 0, 0)`, - }), - }; - +function PrivacyOverlay({ children, ...props }) { const { style, ...restProps } = props; return ( <View - style={{ - display: style?.display ? style.display : 'inline-flex', - ...blurStyle, - ...style, - }} - onPointerEnter={onHover} - onPointerLeave={onHoverEnd} + className={`${css( + [ + { + display: 'inline-flex', + flexGrow: 1, + position: 'relative', + ' > div:first-child': { + opacity: 0, + }, + ' > div:nth-child(2)': { + display: 'flex', + }, + '&:hover': { + ' > div:first-child': { + opacity: 1, + }, + ' > div:nth-child(2)': { + display: 'none', + }, + }, + }, + ], + style, + )}`} {...restProps} > - {children} + <div + className={`${css([ + { + display: 'flex', + flexGrow: 1, + }, + ])}`} + > + {children} + </div> + + <div + aria-hidden="true" + className={`${css({ + flexDirection: 'column', + fontFamily: 'Redacted Script', + height: '100%', + inset: 0, + justifyContent: 'center', + pointerEvents: 'none', + position: 'absolute', + width: '100%', + })}`} + > + {children} + </div> </View> ); } diff --git a/packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx b/packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx index 68599d33a..449c13a4a 100644 --- a/packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx +++ b/packages/desktop-client/src/components/budget/envelope/EnvelopeBudgetComponents.tsx @@ -169,11 +169,6 @@ export const ExpenseGroupMonth = memo(function ExpenseGroupMonth({ valueProps={{ binding: envelopeBudget.groupBalance(id), type: 'financial', - privacyFilter: { - style: { - paddingRight: styles.monthRightPadding, - }, - }, }} /> </View> @@ -431,11 +426,6 @@ export function IncomeGroupMonth({ month }: IncomeGroupMonthProps) { valueProps={{ binding: envelopeBudget.groupIncomeReceived, type: 'financial', - privacyFilter: { - style: { - paddingRight: styles.monthRightPadding, - }, - }, }} /> </View> diff --git a/packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudgetAmount.tsx b/packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudgetAmount.tsx index a03f2560d..04dafd37e 100644 --- a/packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudgetAmount.tsx +++ b/packages/desktop-client/src/components/budget/envelope/budgetsummary/ToBudgetAmount.tsx @@ -64,7 +64,11 @@ export function ToBudgetAmount({ offset={3} triggerProps={{ isDisabled: isTotalsListTooltipDisabled }} > - <PrivacyFilter blurIntensity={7}> + <PrivacyFilter + style={{ + textAlign: 'center', + }} + > <Block onClick={onClick} data-cellname={sheetName} diff --git a/packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx b/packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx index c241bf876..b9bb66eda 100644 --- a/packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx +++ b/packages/desktop-client/src/components/budget/tracking/TrackingBudgetComponents.tsx @@ -178,11 +178,6 @@ export const GroupMonth = memo(function GroupMonth({ valueProps={{ binding: trackingBudget.groupBalance(id), type: 'financial', - privacyFilter: { - style: { - paddingRight: styles.monthRightPadding, - }, - }, }} /> )} diff --git a/packages/desktop-client/src/components/budget/tracking/budgetsummary/Saved.tsx b/packages/desktop-client/src/components/budget/tracking/budgetsummary/Saved.tsx index 5fdb9e1c4..dfadfa943 100644 --- a/packages/desktop-client/src/components/budget/tracking/budgetsummary/Saved.tsx +++ b/packages/desktop-client/src/components/budget/tracking/budgetsummary/Saved.tsx @@ -85,9 +85,7 @@ export function Saved({ projected, style }: SavedProps) { }, ])}`} > - <PrivacyFilter blurIntensity={7}> - {format(saved, 'financial')} - </PrivacyFilter> + <PrivacyFilter>{format(saved, 'financial')}</PrivacyFilter> </View> </Tooltip> </View> diff --git a/packages/desktop-client/src/components/reports/ReportSummary.tsx b/packages/desktop-client/src/components/reports/ReportSummary.tsx index 88968e67a..137ea9270 100644 --- a/packages/desktop-client/src/components/reports/ReportSummary.tsx +++ b/packages/desktop-client/src/components/reports/ReportSummary.tsx @@ -117,9 +117,7 @@ export function ReportSummary({ fontWeight: 800, }} > - <PrivacyFilter blurIntensity={7}> - {amountToCurrency(data[balanceTypeOp])} - </PrivacyFilter> + <PrivacyFilter>{amountToCurrency(data[balanceTypeOp])}</PrivacyFilter> </Text> <Text style={{ fontWeight: 600 }}>For this time period</Text> </View> @@ -154,7 +152,7 @@ export function ReportSummary({ fontWeight: 800, }} > - <PrivacyFilter blurIntensity={7}> + <PrivacyFilter> {!isNaN(average) && integerToCurrency(Math.round(average))} </PrivacyFilter> </Text> diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx index 53ebf2056..346983de0 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReport.tsx +++ b/packages/desktop-client/src/components/reports/reports/CustomReport.tsx @@ -804,7 +804,7 @@ export function CustomReport() { left={<Block>{balanceType}:</Block>} right={ <Text> - <PrivacyFilter blurIntensity={5}> + <PrivacyFilter> {amountToCurrency(data[balanceTypeOp])} </PrivacyFilter> </Text> diff --git a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx index 31a0abace..7f58ab8d0 100644 --- a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx +++ b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx @@ -195,9 +195,7 @@ function NetWorthInner({ widget }) { <View style={{ ...styles.largeText, fontWeight: 400, marginBottom: 5 }} > - <PrivacyFilter blurIntensity={5}> - {integerToCurrency(data.netWorth)} - </PrivacyFilter> + <PrivacyFilter>{integerToCurrency(data.netWorth)}</PrivacyFilter> </View> <PrivacyFilter> <Change amount={data.totalChange} /> diff --git a/packages/desktop-client/src/components/reports/reports/Spending.tsx b/packages/desktop-client/src/components/reports/reports/Spending.tsx index f8d44b93d..7efc495e6 100644 --- a/packages/desktop-client/src/components/reports/reports/Spending.tsx +++ b/packages/desktop-client/src/components/reports/reports/Spending.tsx @@ -474,7 +474,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) { } right={ <Text style={{ fontWeight: 600 }}> - <PrivacyFilter blurIntensity={5}> + <PrivacyFilter> {amountToCurrency( Math.abs(data.intervalData[todayDay].compare), )} @@ -494,7 +494,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) { } right={ <Text style={{ fontWeight: 600 }}> - <PrivacyFilter blurIntensity={5}> + <PrivacyFilter> {amountToCurrency( Math.abs(data.intervalData[todayDay].compareTo), )} @@ -515,7 +515,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) { } right={ <Text style={{ fontWeight: 600 }}> - <PrivacyFilter blurIntensity={5}> + <PrivacyFilter> {amountToCurrency( Math.abs(data.intervalData[todayDay].budget), )} @@ -535,7 +535,7 @@ function SpendingInternal({ widget }: SpendingInternalProps) { } right={ <Text style={{ fontWeight: 600 }}> - <PrivacyFilter blurIntensity={5}> + <PrivacyFilter> {amountToCurrency( Math.abs(data.intervalData[todayDay].average), )} diff --git a/packages/desktop-client/src/components/table.tsx b/packages/desktop-client/src/components/table.tsx index 60f38a0ee..655c8f954 100644 --- a/packages/desktop-client/src/components/table.tsx +++ b/packages/desktop-client/src/components/table.tsx @@ -197,11 +197,6 @@ export function Cell({ privacyFilter={mergeConditionalPrivacyFilterProps( { activationFilters: [!focused, !exposed], - style: { - position: 'absolute', - width: '100%', - height: '100%', - }, }, privacyFilter, )} diff --git a/packages/desktop-client/src/fonts.scss b/packages/desktop-client/src/fonts.scss index dba3274d4..cd47daca1 100644 --- a/packages/desktop-client/src/fonts.scss +++ b/packages/desktop-client/src/fonts.scss @@ -2,3 +2,5 @@ $inter-font-path: '../../../node_modules/inter-ui/Inter (web)' ); @include variable.default; + +@import "@fontsource/redacted-script"; diff --git a/upcoming-release-notes/3377.md b/upcoming-release-notes/3377.md new file mode 100644 index 000000000..2ebd4574f --- /dev/null +++ b/upcoming-release-notes/3377.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [olets] +--- + +Privacy mode: instead of blurring, use an illegible font (#3376) diff --git a/yarn.lock b/yarn.lock index 09207fbfe..11aae8c77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -59,6 +59,7 @@ __metadata: version: 0.0.0-use.local resolution: "@actual-app/web@workspace:packages/desktop-client" dependencies: + "@fontsource/redacted-script": "npm:^5.0.21" "@juggle/resize-observer": "npm:^3.4.0" "@playwright/test": "npm:1.41.1" "@rollup/plugin-inject": "npm:^5.0.5" @@ -1846,6 +1847,13 @@ __metadata: languageName: node linkType: hard +"@fontsource/redacted-script@npm:^5.0.21": + version: 5.0.21 + resolution: "@fontsource/redacted-script@npm:5.0.21" + checksum: 10/93f506c9e8df827ab1872d433a09079c592f3a20a1c36b9a168e68377967d3d1d282fffd51bee973c2ecb253316ff4641d244f8f05242e4aa968a1eb14d065eb + languageName: node + linkType: hard + "@formatjs/ecma402-abstract@npm:1.15.0": version: 1.15.0 resolution: "@formatjs/ecma402-abstract@npm:1.15.0" -- GitLab