diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--9e6aa-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--9e6aa-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png index e8ac3b5c56a..98468b10df9 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--9e6aa-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--9e6aa-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--d270d-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--d270d-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png index 36d8a1a9b35..072e3eb66e1 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--d270d-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--d270d-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--fdd57-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--fdd57-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png index 197e3775696..0325c32d904 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--fdd57-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Envelope-checks-that-clicking--fdd57-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a3783-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a3783-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png index 9a088ae9860..5f7cf85a2bc 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a3783-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a3783-in-the-page-header-opens-the-budget-page-menu-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a8b5e-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a8b5e-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png index 66e399f6db4..56f5581530d 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a8b5e-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--a8b5e-in-the-page-header-opens-the-budget-page-menu-3-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--f8a19-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--f8a19-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png index ac5fb95ee8c..f67cbc6cb25 100644 Binary files a/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--f8a19-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png and b/packages/desktop-client/e2e/budget.mobile.test.ts-snapshots/Mobile-Budget-Tracking-checks-that-clicking--f8a19-in-the-page-header-opens-the-budget-page-menu-2-chromium-linux.png differ diff --git a/packages/desktop-client/src/components/FinancesApp.tsx b/packages/desktop-client/src/components/FinancesApp.tsx index 156cc95cf02..e49c43d0e1d 100644 --- a/packages/desktop-client/src/components/FinancesApp.tsx +++ b/packages/desktop-client/src/components/FinancesApp.tsx @@ -21,6 +21,7 @@ import { useAccounts } from '../hooks/useAccounts'; import { useLocalPref } from '../hooks/useLocalPref'; import { useMetaThemeColor } from '../hooks/useMetaThemeColor'; import { useNavigate } from '../hooks/useNavigate'; +import { useSyncedPref } from '../hooks/useSyncedPref'; import { useSelector, useDispatch } from '../redux'; import { theme } from '../style'; import { getIsOutdated, getLatestVersion } from '../util/versions'; @@ -84,12 +85,67 @@ function RouterBehaviors() { return null; } +function checkForShake(isNarrowWidth, isPrivacyEnabled, setPrivacyEnabledPref) { + if (!isNarrowWidth) { + return; + } + + let lastX = null, + lastY = null, + lastZ = null; + const shakeThreshold = 15; + let timeout = 0; + + const handler = event => { + const { x, y, z } = event.accelerationIncludingGravity; + timeout = Math.max(0, timeout - event.interval); + + if (timeout === 0) { + if (!x || !y || !z) return; + + if (lastX !== null && lastY !== null && lastZ !== null) { + const deltaX = Math.abs(lastX - x); + const deltaY = Math.abs(lastY - y); + const deltaZ = Math.abs(lastZ - z); + + if ( + deltaX > shakeThreshold || + deltaY > shakeThreshold || + deltaZ > shakeThreshold + ) { + isPrivacyEnabled = !isPrivacyEnabled; + setPrivacyEnabledPref(String(isPrivacyEnabled)); + timeout = 1000; + } + } + } + + lastX = x; + lastY = y; + lastZ = z; + }; + + window.addEventListener('devicemotion', handler); + return () => window.removeEventListener('devicemotion', handler); +} + export function FinancesApp() { const { isNarrowWidth } = useResponsive(); useMetaThemeColor(isNarrowWidth ? theme.mobileViewTheme : null); const dispatch = useDispatch(); const { t } = useTranslation(); + const [isPrivacyEnabledPref, setPrivacyEnabledPref] = + useSyncedPref('isPrivacyEnabled'); + useEffect( + () => + checkForShake( + isNarrowWidth, + isPrivacyEnabledPref === 'true', + setPrivacyEnabledPref, + ), + [isNarrowWidth, isPrivacyEnabledPref], + ); const accounts = useAccounts(); const accountsLoaded = useSelector(state => state.queries.accountsLoaded); diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx index 30055290261..3b9ef5f39bf 100644 --- a/packages/desktop-client/src/components/Modals.tsx +++ b/packages/desktop-client/src/components/Modals.tsx @@ -570,6 +570,7 @@ export function Modals() { onAddCategoryGroup={options.onAddCategoryGroup} onToggleHiddenCategories={options.onToggleHiddenCategories} onSwitchBudgetFile={options.onSwitchBudgetFile} + onTogglePrivacyMode={options.onTogglePrivacyMode} /> ); diff --git a/packages/desktop-client/src/components/PrivacyFilter.tsx b/packages/desktop-client/src/components/PrivacyFilter.tsx index 80998adc3bc..c3483781b05 100644 --- a/packages/desktop-client/src/components/PrivacyFilter.tsx +++ b/packages/desktop-client/src/components/PrivacyFilter.tsx @@ -10,8 +10,6 @@ import { css } from '@emotion/css'; import { usePrivacyMode } from '../hooks/usePrivacyMode'; -import { useResponsive } from './responsive/ResponsiveProvider'; - type ConditionalPrivacyFilterProps = { children: ReactNode; privacyFilter?: boolean | PrivacyFilterProps; @@ -51,11 +49,8 @@ export function PrivacyFilter({ ...props }: PrivacyFilterProps) { const privacyMode = usePrivacyMode(); - // Limit mobile support for now. - const { isNarrowWidth } = useResponsive(); const activate = privacyMode && - !isNarrowWidth && (!activationFilters || activationFilters.every(value => typeof value === 'boolean' ? value : value(), diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx index ebddb911320..3f9af2b528a 100644 --- a/packages/desktop-client/src/components/Titlebar.tsx +++ b/packages/desktop-client/src/components/Titlebar.tsx @@ -70,6 +70,7 @@ type PrivacyButtonProps = { }; function PrivacyButton({ style }: PrivacyButtonProps) { + const { t } = useTranslation(); const [isPrivacyEnabledPref, setPrivacyEnabledPref] = useSyncedPref('isPrivacyEnabled'); const isPrivacyEnabled = String(isPrivacyEnabledPref) === 'true'; @@ -91,7 +92,9 @@ function PrivacyButton({ style }: PrivacyButtonProps) { return ( diff --git a/packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx b/packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx index 733076afdad..a81b9f7125a 100644 --- a/packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx +++ b/packages/desktop-client/src/components/modals/BudgetPageMenuModal.tsx @@ -8,6 +8,7 @@ import { Menu } from '@actual-app/components/menu'; import { styles } from '@actual-app/components/styles'; import { useLocalPref } from '../../hooks/useLocalPref'; +import { useSyncedPref } from '../../hooks/useSyncedPref'; import { theme } from '../../style'; import { Modal, ModalCloseButton, ModalHeader } from '../common/Modal'; @@ -17,6 +18,7 @@ export function BudgetPageMenuModal({ onAddCategoryGroup, onToggleHiddenCategories, onSwitchBudgetFile, + onTogglePrivacyMode, }: BudgetPageMenuModalProps) { const defaultMenuItemStyle: CSSProperties = { ...styles.mobileMenuItem, @@ -38,6 +40,7 @@ export function BudgetPageMenuModal({ onAddCategoryGroup={onAddCategoryGroup} onToggleHiddenCategories={onToggleHiddenCategories} onSwitchBudgetFile={onSwitchBudgetFile} + onTogglePrivacyMode={onTogglePrivacyMode} /> )} @@ -52,15 +55,18 @@ type BudgetPageMenuProps = Omit< onAddCategoryGroup: () => void; onToggleHiddenCategories: () => void; onSwitchBudgetFile: () => void; + onTogglePrivacyMode: () => void; }; function BudgetPageMenu({ onAddCategoryGroup, onToggleHiddenCategories, onSwitchBudgetFile, + onTogglePrivacyMode, ...props }: BudgetPageMenuProps) { const [showHiddenCategories] = useLocalPref('budget.showHiddenCategories'); + const [isPrivacyEnabled] = useSyncedPref('isPrivacyEnabled'); const onMenuSelect = (name: string) => { switch (name) { @@ -76,6 +82,9 @@ function BudgetPageMenu({ case 'switch-budget-file': onSwitchBudgetFile?.(); break; + case 'toggle-privacy-filter': + onTogglePrivacyMode?.(); + break; default: throw new Error(`Unrecognized menu item: ${name}`); } @@ -95,6 +104,13 @@ function BudgetPageMenu({ name: 'toggle-hidden-categories', text: `${!showHiddenCategories ? t('Show hidden categories') : t('Hide hidden categories')}`, }, + { + name: 'toggle-privacy-filter', + text: + isPrivacyEnabled === 'true' + ? t('Disable privacy mode') + : t('Enable privacy mode'), + }, { name: 'switch-budget-file', text: t('Switch budget file'), diff --git a/packages/loot-core/src/client/state-types/modals.d.ts b/packages/loot-core/src/client/state-types/modals.d.ts index 7fb3c44fdad..9d11d403330 100644 --- a/packages/loot-core/src/client/state-types/modals.d.ts +++ b/packages/loot-core/src/client/state-types/modals.d.ts @@ -303,6 +303,7 @@ type FinanceModals = { onAddCategoryGroup: () => void; onToggleHiddenCategories: () => void; onSwitchBudgetFile: () => void; + onTogglePrivacyMode: () => void; }; 'envelope-budget-month-menu': { month: string; diff --git a/upcoming-release-notes/4510.md b/upcoming-release-notes/4510.md new file mode 100644 index 00000000000..d0cd42ebb2a --- /dev/null +++ b/upcoming-release-notes/4510.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [rugulous] +--- + +Enable the privacy filter option on mobile/small screen devices