fix(app): make click-through the default and move animation pausing to Accessibility (#1722)

This commit is contained in:
Hampus authored and GitHub committed 2026-08-18 19:40:35 +02:00
1 parent 9e89539f0a
commit 4bbfee4cec
19 files changed
+96 -248

No files matched your search

@@ -3,6 +3,7 @@
import {
MiddleClickAutoscrollControl,
SmoothScrollingControl,
StayInteractiveUnfocusedControl,
TextSelectionControl,
VideoSeekThumbnailsControl,
} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedAccessibilityControls';
@@ -34,10 +35,8 @@ import {
} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedChatControls';
import {DeveloperModeControl} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedClientDeveloperControls';
import {
FirstClickPassThroughControl,
HardwareAccelerationControl,
NativeTitleBarControl,
StayInteractiveUnfocusedControl,
} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedDesktopControls';
import {UnreadBadgeCustomizationControl} from '@app/features/user/components/modals/tabs/advanced_settings_tab/AdvancedExperimentalControls';
import {
@@ -90,8 +89,7 @@ export const DIRECT_CONTROL_ITEM_IDS = new Set([
'voice-video-screen-share-encoder-controls',
'advanced-unread-badge-customization',
'client-developer-mode',
'advanced-stay-interactive-unfocused',
'first-click-pass-through',
'accessibility-stay-interactive-unfocused',
'advanced-native-title-bar',
'advanced-hardware-acceleration',
]);
@@ -126,8 +124,7 @@ export const COMPACT_SWITCH_CONTROL_ITEM_IDS = new Set([
'voice-video-openh264-codec',
'advanced-unread-badge-customization',
'client-developer-mode',
'advanced-stay-interactive-unfocused',
'first-click-pass-through',
'accessibility-stay-interactive-unfocused',
'advanced-native-title-bar',
'advanced-hardware-acceleration',
]);
@@ -298,14 +295,10 @@ export const AdvancedSettingControl = observer(({item}: {item: SearchableSetting
return (
<DeveloperModeControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.developer-mode-control" />
);
case 'advanced-stay-interactive-unfocused':
case 'accessibility-stay-interactive-unfocused':
return (
<StayInteractiveUnfocusedControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.stay-interactive-unfocused-control" />
);
case 'first-click-pass-through':
return (
<FirstClickPassThroughControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.first-click-pass-through-control" />
);
case 'advanced-native-title-bar':
return (
<NativeTitleBarControl data-flx="user.advanced-setting-direct-controls.advanced-setting-control.native-title-bar-control" />
@@ -32,6 +32,14 @@ const CONTENT_ANIMATIONS_STAY_IN_ANIMATION_TAB_DESCRIPTOR = msg({
message: 'Animated emojis, GIFs and stickers stay under your control in the Animation tab.',
comment: 'Extra hint shown beneath the reduce motion toggle while reduced motion is active.',
});
const STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR = msg({
message: 'Stay fully interactive when unfocused',
comment: 'Label in the motion tab.',
});
const KEEP_ANIMATIONS_GIF_PLAYBACK_HOVER_EFFECTS_AND_TOOLTIPS_RUNNING_DESCRIPTOR = msg({
message: 'Keep animations, GIF playback, hover effects, and tooltips running while the window is unfocused.',
comment: 'Description text in the motion tab.',
});
export const MotionTabContent: React.FC = observer(() => {
const {i18n} = useLingui();
const syncReducedMotionWithSystem = Accessibility.syncReducedMotionWithSystem;
@@ -60,6 +68,13 @@ export const MotionTabContent: React.FC = observer(() => {
onChange={(value) => AccessibilityCommands.update({reducedMotionOverride: value})}
data-flx="user.accessibility-tab.motion-tab.motion-tab-content.switch.update--2"
/>
<Switch
label={i18n._(STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR)}
description={i18n._(KEEP_ANIMATIONS_GIF_PLAYBACK_HOVER_EFFECTS_AND_TOOLTIPS_RUNNING_DESCRIPTOR)}
value={Accessibility.stayInteractiveWhenUnfocused}
onChange={(value) => AccessibilityCommands.update({stayInteractiveWhenUnfocused: value})}
data-flx="user.accessibility-tab.motion-tab.motion-tab-content.switch.update--3"
/>
</>
);
});
@@ -32,6 +32,10 @@ const SMOOTH_SCROLLING_DESCRIPTOR = msg({
message: 'Smooth scrolling',
comment: 'Short label for an advanced desktop scrolling toggle.',
});
const STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR = msg({
message: 'Stay fully interactive when unfocused',
comment: 'Short label for an advanced app interaction toggle.',
});
const USE_AUTOSCROLLING_DESCRIPTOR = msg({
message: 'Use autoscrolling',
comment: 'Short label for an advanced desktop scrolling toggle.',
@@ -135,6 +139,19 @@ export const TextSelectionControl = observer(() => {
);
});
export const StayInteractiveUnfocusedControl = observer(() => {
const {i18n} = useLingui();
return (
<Switch
ariaLabel={i18n._(STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR)}
value={Accessibility.stayInteractiveWhenUnfocused}
onChange={(value) => AccessibilityCommands.update({stayInteractiveWhenUnfocused: value})}
compact
data-flx="user.advanced-settings-tab.switch.stay-interactive-unfocused"
/>
);
});
export const VideoSeekThumbnailsControl = observer(() => {
const {i18n} = useLingui();
return (
@@ -1,7 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import * as AccessibilityCommands from '@app/features/accessibility/commands/AccessibilityCommands';
import Accessibility from '@app/features/accessibility/state/Accessibility';
import {ConfirmModal} from '@app/features/app/components/dialogs/ConfirmModal';
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
import {
@@ -25,14 +23,6 @@ import {Trans, useLingui} from '@lingui/react/macro';
import {observer} from 'mobx-react-lite';
import {useCallback, useLayoutEffect, useState} from 'react';
const STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR = msg({
message: 'Stay fully interactive when unfocused',
comment: 'Short label for an advanced desktop preference.',
});
const FIRST_CLICK_PASS_THROUGH_WHEN_UNFOCUSED_DESCRIPTOR = msg({
message: 'First click pass-through when unfocused',
comment: 'Short label for an advanced desktop preference.',
});
const USE_NATIVE_TITLE_BAR_DESCRIPTOR = msg({
message: 'Use native title bar',
comment: 'Short label for an advanced desktop preference.',
@@ -128,32 +118,6 @@ function useDesktopTroubleshootingSettings() {
};
}
export const StayInteractiveUnfocusedControl = observer(() => {
const {i18n} = useLingui();
return (
<Switch
ariaLabel={i18n._(STAY_FULLY_INTERACTIVE_WHEN_UNFOCUSED_DESCRIPTOR)}
value={Accessibility.stayInteractiveWhenUnfocused}
onChange={(value) => AccessibilityCommands.update({stayInteractiveWhenUnfocused: value})}
compact
data-flx="user.advanced-settings-tab.switch.stay-interactive-unfocused"
/>
);
});
export const FirstClickPassThroughControl = observer(() => {
const {i18n} = useLingui();
return (
<Switch
ariaLabel={i18n._(FIRST_CLICK_PASS_THROUGH_WHEN_UNFOCUSED_DESCRIPTOR)}
value={Accessibility.firstClickPassThroughWhenUnfocused}
onChange={(value) => AccessibilityCommands.update({firstClickPassThroughWhenUnfocused: value})}
compact
data-flx="user.advanced-settings-tab.switch.first-click-pass-through"
/>
);
});
export const NativeTitleBarControl = observer(() => {
const {i18n} = useLingui();
const {desktopWindowBehavior, desktopWindowBehaviorBusy, updateDesktopWindowBehavior} =