Skip to content

Commit b032b45

Browse files
peter-sandersonkomret
authored andcommitted
feat(suite): haptic-feedback settings, brightness settings
(cherry picked from commit ad333dd)
1 parent f879a64 commit b032b45

File tree

11 files changed

+183
-5
lines changed

11 files changed

+183
-5
lines changed

packages/connect/src/api/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export { default as recoveryDevice } from './recoveryDevice';
4646
// export { default as renderWebUSBButton } from './composeTransaction';
4747
export { default as requestLogin } from './requestLogin';
4848
export { default as resetDevice } from './resetDevice';
49+
export { default as setBrightness } from './setBrightness';
4950
export { default as setBusy } from './setBusy';
5051
export { default as setProxy } from './setProxy';
5152
export { default as signMessage } from './signMessage';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// origin: https://github.com/trezor/connect/blob/develop/src/js/core/methods/SetBrightness.js
2+
3+
import { AbstractMethod } from '../core/AbstractMethod';
4+
import { PROTO } from '../constants';
5+
import { Assert } from '@trezor/schema-utils';
6+
7+
export default class SetBrightness extends AbstractMethod<'setBrightness', PROTO.SetBrightness> {
8+
init() {
9+
this.requiredPermissions = ['management'];
10+
this.useDeviceState = false;
11+
const { payload } = this;
12+
13+
Assert(PROTO.SetBrightness, payload);
14+
15+
this.params = {
16+
value: payload.value,
17+
};
18+
}
19+
20+
async run() {
21+
const cmd = this.device.getCommands();
22+
const response = await cmd.typedCall('SetBrightness', 'Success', this.params);
23+
24+
return response.message;
25+
}
26+
}

packages/connect/src/factory.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ export const factory = ({
253253

254254
rebootToBootloader: params => call({ ...params, method: 'rebootToBootloader' }),
255255

256+
setBrightness: params => call({ ...params, method: 'setBrightness' }),
257+
256258
setBusy: params => call({ ...params, method: 'setBusy' }),
257259

258260
setProxy: params => call({ ...params, method: 'setProxy' }),

packages/connect/src/types/api/index.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ import { blockchainSubscribeFiatRates } from './blockchainSubscribeFiatRates';
1818
import { blockchainUnsubscribe } from './blockchainUnsubscribe';
1919
import { blockchainUnsubscribeFiatRates } from './blockchainUnsubscribeFiatRates';
2020
import { cancel } from './cancel';
21+
import { cancelCoinjoinAuthorization } from './cancelCoinjoinAuthorization';
22+
import { cardanoComposeTransaction } from './cardanoComposeTransaction';
2123
import { cardanoGetAddress } from './cardanoGetAddress';
2224
import { cardanoGetNativeScriptHash } from './cardanoGetNativeScriptHash';
2325
import { cardanoGetPublicKey } from './cardanoGetPublicKey';
2426
import { cardanoSignTransaction } from './cardanoSignTransaction';
25-
import { cardanoComposeTransaction } from './cardanoComposeTransaction';
2627
import { changeLanguage } from './changeLanguage';
2728
import { changePin } from './changePin';
2829
import { changeWipeCode } from './changeWipeCode';
30+
import { checkFirmwareAuthenticity } from './checkFirmwareAuthenticity';
2931
import { cipherKeyValue } from './cipherKeyValue';
3032
import { composeTransaction } from './composeTransaction';
3133
import { disableWebUSB } from './disableWebUSB';
@@ -66,12 +68,14 @@ import { requestWebUSBDevice } from './requestWebUSBDevice';
6668
import { resetDevice } from './resetDevice';
6769
import { rippleGetAddress } from './rippleGetAddress';
6870
import { rippleSignTransaction } from './rippleSignTransaction';
71+
import { setBrightness } from './setBrightness';
6972
import { setBusy } from './setBusy';
7073
import { setProxy } from './setProxy';
74+
import { showDeviceTutorial } from './showDeviceTutorial';
7175
import { signMessage } from './signMessage';
7276
import { signTransaction } from './signTransaction';
73-
import { solanaGetPublicKey } from './solanaGetPublicKey';
7477
import { solanaGetAddress } from './solanaGetAddress';
78+
import { solanaGetPublicKey } from './solanaGetPublicKey';
7579
import { solanaSignTransaction } from './solanaSignTransaction';
7680
import { stellarGetAddress } from './stellarGetAddress';
7781
import { stellarSignTransaction } from './stellarSignTransaction';
@@ -82,9 +86,6 @@ import { uiResponse } from './uiResponse';
8286
import { unlockPath } from './unlockPath';
8387
import { verifyMessage } from './verifyMessage';
8488
import { wipeDevice } from './wipeDevice';
85-
import { checkFirmwareAuthenticity } from './checkFirmwareAuthenticity';
86-
import { cancelCoinjoinAuthorization } from './cancelCoinjoinAuthorization';
87-
import { showDeviceTutorial } from './showDeviceTutorial';
8889

8990
export interface TrezorConnect {
9091
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/applyFlags.md
@@ -295,6 +296,9 @@ export interface TrezorConnect {
295296
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/rippleSignTransaction.md
296297
rippleSignTransaction: typeof rippleSignTransaction;
297298

299+
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/setBrightness.md
300+
setBrightness: typeof setBrightness;
301+
298302
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/setBusy.md
299303
setBusy: typeof setBusy;
300304

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { PROTO } from '../../constants';
2+
import type { Params, Response } from '../params';
3+
4+
export declare function setBrightness(params: Params<PROTO.SetBrightness>): Response<PROTO.Success>;

packages/suite-analytics/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ export enum EventType {
6767
SettingsDeviceChangeLabel = 'settings/device/change-label',
6868
SettingsDeviceUpdateAutoLock = 'settings/device/update-auto-lock',
6969
SettingsDeviceChangeOrientation = 'settings/device/change-orientation',
70+
SettingsDeviceChangeHapticFeedback = 'settings/device/change-haptic-feedback',
71+
SettingsDeviceChangeBrightness = 'settings/device/change-brightness',
7072
SettingsDeviceWipe = 'settings/device/wipe',
7173
SettingsDeviceChangePassphraseProtection = 'settings/device/change-passphrase-protection',
7274
SettingsGeneralChangeLanguage = 'settings/general/change-language',

packages/suite-analytics/src/types/events.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,18 @@ export type SuiteAnalyticsEvent =
281281
value: 0 | 90 | 180 | 270;
282282
};
283283
}
284+
| {
285+
type: EventType.SettingsDeviceChangeHapticFeedback;
286+
payload: {
287+
value: boolean;
288+
};
289+
}
290+
| {
291+
type: EventType.SettingsDeviceChangeBrightness;
292+
payload: {
293+
value?: number;
294+
};
295+
}
284296
| { type: EventType.SettingsDeviceWipe }
285297
| {
286298
type: EventType.SettingsDeviceChangePassphraseProtection;

packages/suite/src/support/messages.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,26 @@ export default defineMessages({
26612661
defaultMessage: 'Change PIN',
26622662
id: 'TR_DEVICE_SETTINGS_CHANGE_PIN_TITLE',
26632663
},
2664+
TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC: {
2665+
defaultMessage: 'Turn on on haptic feedback for device interactions',
2666+
id: 'TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC',
2667+
},
2668+
TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE: {
2669+
defaultMessage: 'Haptic feedback',
2670+
id: 'TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE',
2671+
},
2672+
TR_DEVICE_SETTINGS_BRIGHTNESS_DESC: {
2673+
defaultMessage: 'Enable brightness customization for the display on the device',
2674+
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_DESC',
2675+
},
2676+
TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE: {
2677+
defaultMessage: 'Display Brightness',
2678+
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE',
2679+
},
2680+
TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON: {
2681+
defaultMessage: 'Change Brightness',
2682+
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON',
2683+
},
26642684
TR_DEVICE_SETTINGS_WIPE_CODE_TITLE: {
26652685
defaultMessage: 'Set up wipe code',
26662686
id: 'TR_DEVICE_SETTINGS_WIPE_CODE_TITLE',
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import TrezorConnect from '@trezor/connect';
2+
import { analytics, EventType } from '@trezor/suite-analytics';
3+
import { SettingsSectionItem } from 'src/components/settings';
4+
import { ActionButton, ActionColumn, TextColumn, Translation } from 'src/components/suite';
5+
import { SettingsAnchor } from 'src/constants/suite/anchors';
6+
import { useDevice, useSelector } from '../../../hooks/suite';
7+
8+
interface DeviceLabelProps {
9+
isDeviceLocked: boolean;
10+
}
11+
12+
export const Brightness = ({ isDeviceLocked }: DeviceLabelProps) => {
13+
const { device } = useDevice();
14+
15+
const showDebugMenu = useSelector(state => state.suite.settings.debug.showDebugMenu);
16+
17+
const isSupportedDevice = device?.features?.capabilities?.includes('Capability_Brightness');
18+
19+
if (!showDebugMenu || !isSupportedDevice) {
20+
return null;
21+
}
22+
23+
const handleClick = async () => {
24+
const result = await TrezorConnect.setBrightness({});
25+
if (result.success) {
26+
analytics.report({
27+
type: EventType.SettingsDeviceChangeBrightness,
28+
payload: {},
29+
});
30+
}
31+
};
32+
33+
return (
34+
<SettingsSectionItem anchorId={SettingsAnchor.PinProtection}>
35+
<TextColumn
36+
title={<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE" />}
37+
description={<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_DESC" />}
38+
/>
39+
<ActionColumn>
40+
<ActionButton
41+
onClick={handleClick}
42+
isDisabled={isDeviceLocked}
43+
variant="secondary"
44+
data-test="@settings/device/brightness-switch"
45+
>
46+
<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON" />
47+
</ActionButton>
48+
</ActionColumn>
49+
</SettingsSectionItem>
50+
);
51+
};
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Switch } from '@trezor/components';
2+
import { SettingsSectionItem } from 'src/components/settings';
3+
import { ActionColumn, TextColumn, Translation } from 'src/components/suite';
4+
import { SettingsAnchor } from 'src/constants/suite/anchors';
5+
import { useDevice, useDispatch } from '../../../hooks/suite';
6+
import { applySettings } from 'src/actions/settings/deviceSettingsActions';
7+
import { analytics, EventType } from '@trezor/suite-analytics';
8+
9+
interface DeviceLabelProps {
10+
isDeviceLocked: boolean;
11+
}
12+
13+
export const HapticFeedback = ({ isDeviceLocked }: DeviceLabelProps) => {
14+
const dispatch = useDispatch();
15+
const { device } = useDevice();
16+
17+
const isSupportedDevice = device?.features?.capabilities?.includes('Capability_Haptic');
18+
19+
if (!isSupportedDevice) {
20+
return null;
21+
}
22+
23+
const hapticEnabled = device?.features?.haptic_feedback ?? false;
24+
25+
const handleChange = async () => {
26+
const result = await dispatch(applySettings({ haptic_feedback: !hapticEnabled }));
27+
28+
if (result?.success) {
29+
analytics.report({
30+
type: EventType.SettingsDeviceChangeHapticFeedback,
31+
payload: { value: !hapticEnabled },
32+
});
33+
}
34+
};
35+
36+
return (
37+
<SettingsSectionItem anchorId={SettingsAnchor.PinProtection}>
38+
<TextColumn
39+
title={<Translation id="TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE" />}
40+
description={<Translation id="TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC" />}
41+
/>
42+
<ActionColumn>
43+
<Switch
44+
isChecked={hapticEnabled}
45+
onChange={handleChange}
46+
isDisabled={isDeviceLocked}
47+
dataTest="@settings/device/haptic-switch"
48+
/>
49+
</ActionColumn>
50+
</SettingsSectionItem>
51+
);
52+
};

packages/suite/src/views/settings/SettingsDevice/SettingsDevice.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import { ChangeLanguage } from './ChangeLanguage';
3030
import { EnableViewOnly } from './EnableViewOnly';
3131
import { selectSuiteFlags } from 'src/reducers/suite/suiteReducer';
3232
import { isRecoveryInProgress } from '../../../utils/device/isRecoveryInProgress';
33+
import { HapticFeedback } from './HapticFeedback';
34+
import { Brightness } from './Brightness';
3335

3436
const deviceSettingsUnavailable = (device?: TrezorDevice, transport?: Partial<TransportInfo>) => {
3537
const noTransportAvailable = transport && !transport.type;
@@ -161,6 +163,8 @@ export const SettingsDevice = () => {
161163
<DeviceLabel isDeviceLocked={isDeviceLocked} />
162164
<Homescreen isDeviceLocked={isDeviceLocked} />
163165
<DisplayRotation isDeviceLocked={isDeviceLocked} />
166+
<Brightness isDeviceLocked={isDeviceLocked} />
167+
<HapticFeedback isDeviceLocked={isDeviceLocked} />
164168
{pinProtection && <AutoLock isDeviceLocked={isDeviceLocked} />}
165169
</SettingsSection>
166170
</>

0 commit comments

Comments
 (0)