Skip to content

Commit

Permalink
feat(suite): haptic-feedback settings, brightness settings
Browse files Browse the repository at this point in the history
(cherry picked from commit ad333dd)
  • Loading branch information
peter-sanderson authored and komret committed Jun 6, 2024
1 parent f879a64 commit b032b45
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/connect/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export { default as recoveryDevice } from './recoveryDevice';
// export { default as renderWebUSBButton } from './composeTransaction';
export { default as requestLogin } from './requestLogin';
export { default as resetDevice } from './resetDevice';
export { default as setBrightness } from './setBrightness';
export { default as setBusy } from './setBusy';
export { default as setProxy } from './setProxy';
export { default as signMessage } from './signMessage';
Expand Down
26 changes: 26 additions & 0 deletions packages/connect/src/api/setBrightness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// origin: https://github.com/trezor/connect/blob/develop/src/js/core/methods/SetBrightness.js

import { AbstractMethod } from '../core/AbstractMethod';
import { PROTO } from '../constants';
import { Assert } from '@trezor/schema-utils';

export default class SetBrightness extends AbstractMethod<'setBrightness', PROTO.SetBrightness> {
init() {
this.requiredPermissions = ['management'];
this.useDeviceState = false;
const { payload } = this;

Assert(PROTO.SetBrightness, payload);

this.params = {
value: payload.value,
};
}

async run() {
const cmd = this.device.getCommands();
const response = await cmd.typedCall('SetBrightness', 'Success', this.params);

return response.message;
}
}
2 changes: 2 additions & 0 deletions packages/connect/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ export const factory = ({

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

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

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

setProxy: params => call({ ...params, method: 'setProxy' }),
Expand Down
14 changes: 9 additions & 5 deletions packages/connect/src/types/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ import { blockchainSubscribeFiatRates } from './blockchainSubscribeFiatRates';
import { blockchainUnsubscribe } from './blockchainUnsubscribe';
import { blockchainUnsubscribeFiatRates } from './blockchainUnsubscribeFiatRates';
import { cancel } from './cancel';
import { cancelCoinjoinAuthorization } from './cancelCoinjoinAuthorization';
import { cardanoComposeTransaction } from './cardanoComposeTransaction';
import { cardanoGetAddress } from './cardanoGetAddress';
import { cardanoGetNativeScriptHash } from './cardanoGetNativeScriptHash';
import { cardanoGetPublicKey } from './cardanoGetPublicKey';
import { cardanoSignTransaction } from './cardanoSignTransaction';
import { cardanoComposeTransaction } from './cardanoComposeTransaction';
import { changeLanguage } from './changeLanguage';
import { changePin } from './changePin';
import { changeWipeCode } from './changeWipeCode';
import { checkFirmwareAuthenticity } from './checkFirmwareAuthenticity';
import { cipherKeyValue } from './cipherKeyValue';
import { composeTransaction } from './composeTransaction';
import { disableWebUSB } from './disableWebUSB';
Expand Down Expand Up @@ -66,12 +68,14 @@ import { requestWebUSBDevice } from './requestWebUSBDevice';
import { resetDevice } from './resetDevice';
import { rippleGetAddress } from './rippleGetAddress';
import { rippleSignTransaction } from './rippleSignTransaction';
import { setBrightness } from './setBrightness';
import { setBusy } from './setBusy';
import { setProxy } from './setProxy';
import { showDeviceTutorial } from './showDeviceTutorial';
import { signMessage } from './signMessage';
import { signTransaction } from './signTransaction';
import { solanaGetPublicKey } from './solanaGetPublicKey';
import { solanaGetAddress } from './solanaGetAddress';
import { solanaGetPublicKey } from './solanaGetPublicKey';
import { solanaSignTransaction } from './solanaSignTransaction';
import { stellarGetAddress } from './stellarGetAddress';
import { stellarSignTransaction } from './stellarSignTransaction';
Expand All @@ -82,9 +86,6 @@ import { uiResponse } from './uiResponse';
import { unlockPath } from './unlockPath';
import { verifyMessage } from './verifyMessage';
import { wipeDevice } from './wipeDevice';
import { checkFirmwareAuthenticity } from './checkFirmwareAuthenticity';
import { cancelCoinjoinAuthorization } from './cancelCoinjoinAuthorization';
import { showDeviceTutorial } from './showDeviceTutorial';

export interface TrezorConnect {
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/applyFlags.md
Expand Down Expand Up @@ -295,6 +296,9 @@ export interface TrezorConnect {
// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/rippleSignTransaction.md
rippleSignTransaction: typeof rippleSignTransaction;

// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/setBrightness.md
setBrightness: typeof setBrightness;

// https://github.com/trezor/trezor-suite/blob/develop/docs/packages/connect/methods/setBusy.md
setBusy: typeof setBusy;

Expand Down
4 changes: 4 additions & 0 deletions packages/connect/src/types/api/setBrightness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { PROTO } from '../../constants';
import type { Params, Response } from '../params';

export declare function setBrightness(params: Params<PROTO.SetBrightness>): Response<PROTO.Success>;
2 changes: 2 additions & 0 deletions packages/suite-analytics/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export enum EventType {
SettingsDeviceChangeLabel = 'settings/device/change-label',
SettingsDeviceUpdateAutoLock = 'settings/device/update-auto-lock',
SettingsDeviceChangeOrientation = 'settings/device/change-orientation',
SettingsDeviceChangeHapticFeedback = 'settings/device/change-haptic-feedback',
SettingsDeviceChangeBrightness = 'settings/device/change-brightness',
SettingsDeviceWipe = 'settings/device/wipe',
SettingsDeviceChangePassphraseProtection = 'settings/device/change-passphrase-protection',
SettingsGeneralChangeLanguage = 'settings/general/change-language',
Expand Down
12 changes: 12 additions & 0 deletions packages/suite-analytics/src/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,18 @@ export type SuiteAnalyticsEvent =
value: 0 | 90 | 180 | 270;
};
}
| {
type: EventType.SettingsDeviceChangeHapticFeedback;
payload: {
value: boolean;
};
}
| {
type: EventType.SettingsDeviceChangeBrightness;
payload: {
value?: number;
};
}
| { type: EventType.SettingsDeviceWipe }
| {
type: EventType.SettingsDeviceChangePassphraseProtection;
Expand Down
20 changes: 20 additions & 0 deletions packages/suite/src/support/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2661,6 +2661,26 @@ export default defineMessages({
defaultMessage: 'Change PIN',
id: 'TR_DEVICE_SETTINGS_CHANGE_PIN_TITLE',
},
TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC: {
defaultMessage: 'Turn on on haptic feedback for device interactions',
id: 'TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC',
},
TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE: {
defaultMessage: 'Haptic feedback',
id: 'TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE',
},
TR_DEVICE_SETTINGS_BRIGHTNESS_DESC: {
defaultMessage: 'Enable brightness customization for the display on the device',
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_DESC',
},
TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE: {
defaultMessage: 'Display Brightness',
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE',
},
TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON: {
defaultMessage: 'Change Brightness',
id: 'TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON',
},
TR_DEVICE_SETTINGS_WIPE_CODE_TITLE: {
defaultMessage: 'Set up wipe code',
id: 'TR_DEVICE_SETTINGS_WIPE_CODE_TITLE',
Expand Down
51 changes: 51 additions & 0 deletions packages/suite/src/views/settings/SettingsDevice/Brightness.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import TrezorConnect from '@trezor/connect';
import { analytics, EventType } from '@trezor/suite-analytics';
import { SettingsSectionItem } from 'src/components/settings';
import { ActionButton, ActionColumn, TextColumn, Translation } from 'src/components/suite';
import { SettingsAnchor } from 'src/constants/suite/anchors';
import { useDevice, useSelector } from '../../../hooks/suite';

interface DeviceLabelProps {
isDeviceLocked: boolean;
}

export const Brightness = ({ isDeviceLocked }: DeviceLabelProps) => {
const { device } = useDevice();

const showDebugMenu = useSelector(state => state.suite.settings.debug.showDebugMenu);

const isSupportedDevice = device?.features?.capabilities?.includes('Capability_Brightness');

if (!showDebugMenu || !isSupportedDevice) {
return null;
}

const handleClick = async () => {
const result = await TrezorConnect.setBrightness({});
if (result.success) {
analytics.report({
type: EventType.SettingsDeviceChangeBrightness,
payload: {},
});
}
};

return (
<SettingsSectionItem anchorId={SettingsAnchor.PinProtection}>
<TextColumn
title={<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_TITLE" />}
description={<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_DESC" />}
/>
<ActionColumn>
<ActionButton
onClick={handleClick}
isDisabled={isDeviceLocked}
variant="secondary"
data-test="@settings/device/brightness-switch"
>
<Translation id="TR_DEVICE_SETTINGS_BRIGHTNESS_BUTTON" />
</ActionButton>
</ActionColumn>
</SettingsSectionItem>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Switch } from '@trezor/components';
import { SettingsSectionItem } from 'src/components/settings';
import { ActionColumn, TextColumn, Translation } from 'src/components/suite';
import { SettingsAnchor } from 'src/constants/suite/anchors';
import { useDevice, useDispatch } from '../../../hooks/suite';
import { applySettings } from 'src/actions/settings/deviceSettingsActions';
import { analytics, EventType } from '@trezor/suite-analytics';

interface DeviceLabelProps {
isDeviceLocked: boolean;
}

export const HapticFeedback = ({ isDeviceLocked }: DeviceLabelProps) => {
const dispatch = useDispatch();
const { device } = useDevice();

const isSupportedDevice = device?.features?.capabilities?.includes('Capability_Haptic');

if (!isSupportedDevice) {
return null;
}

const hapticEnabled = device?.features?.haptic_feedback ?? false;

const handleChange = async () => {
const result = await dispatch(applySettings({ haptic_feedback: !hapticEnabled }));

if (result?.success) {
analytics.report({
type: EventType.SettingsDeviceChangeHapticFeedback,
payload: { value: !hapticEnabled },
});
}
};

return (
<SettingsSectionItem anchorId={SettingsAnchor.PinProtection}>
<TextColumn
title={<Translation id="TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_TITLE" />}
description={<Translation id="TR_DEVICE_SETTINGS_HAPTIC_FEEDBACK_DESC" />}
/>
<ActionColumn>
<Switch
isChecked={hapticEnabled}
onChange={handleChange}
isDisabled={isDeviceLocked}
dataTest="@settings/device/haptic-switch"
/>
</ActionColumn>
</SettingsSectionItem>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { ChangeLanguage } from './ChangeLanguage';
import { EnableViewOnly } from './EnableViewOnly';
import { selectSuiteFlags } from 'src/reducers/suite/suiteReducer';
import { isRecoveryInProgress } from '../../../utils/device/isRecoveryInProgress';
import { HapticFeedback } from './HapticFeedback';
import { Brightness } from './Brightness';

const deviceSettingsUnavailable = (device?: TrezorDevice, transport?: Partial<TransportInfo>) => {
const noTransportAvailable = transport && !transport.type;
Expand Down Expand Up @@ -161,6 +163,8 @@ export const SettingsDevice = () => {
<DeviceLabel isDeviceLocked={isDeviceLocked} />
<Homescreen isDeviceLocked={isDeviceLocked} />
<DisplayRotation isDeviceLocked={isDeviceLocked} />
<Brightness isDeviceLocked={isDeviceLocked} />
<HapticFeedback isDeviceLocked={isDeviceLocked} />
{pinProtection && <AutoLock isDeviceLocked={isDeviceLocked} />}
</SettingsSection>
</>
Expand Down

0 comments on commit b032b45

Please sign in to comment.