Skip to content

Commit dad522c

Browse files
author
Lucas
committed
[DDW-786] Discreet mode - Create the TopBar icon (#2725)
* [DDW-786] Added discreet mode toggle component * [DDW-789] Remove specific styles from component * [DDW-789] Fix translations * [DDW-789] CHANGELOG * [DDW-789] Fix eslint issue * [DDW-789] Remove popover theme variables * [DDW-789] Increase height for hide icon * [DDW-789] Remove style * [DDW-789] Rearrange icons to group by action or info * [DDW-786] Add japanese translations * [DDW-786] Rearrange icons order * [DDW-786] Add opacity * [DDW-786] Add isDiscreetMode control to story * [DDW-786] Fix gap width * [DDW-786] Fix default message * [DDW-786] Update to use mobx feature pattern * [DDW-786] Fix style
1 parent 1fc1e18 commit dad522c

File tree

13 files changed

+356
-100
lines changed

13 files changed

+356
-100
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
## 4.5.0
2525

2626
### Features
27-
- Implemented "discreet mode" ([PR 2723](https://github.com/input-output-hk/daedalus/pull/2723), [PR 2724](https://github.com/input-output-hk/daedalus/pull/2724))
27+
28+
- Implemented "discreet mode" ([PR 2723](https://github.com/input-output-hk/daedalus/pull/2723), [PR 2724](https://github.com/input-output-hk/daedalus/pull/2724), [PR 2725](https://github.com/input-output-hk/daedalus/pull/2725))
2829
- Implemented "Catalyst Fund7" voting registration changes ([PR 2732](https://github.com/input-output-hk/daedalus/pull/2732))
2930
- Added "Over-saturation" warning in the delegation wizard ([PR 2733](https://github.com/input-output-hk/daedalus/pull/2733), [PR 2738](https://github.com/input-output-hk/daedalus/pull/2738))
3031
- Added Catalyst footer links ([PR 2721](https://github.com/input-output-hk/daedalus/pull/2721))

source/renderer/app/components/layout/TopBar.scss

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,32 @@
8888
position: absolute;
8989
width: calc(100% - 140px);
9090
}
91+
92+
.discreetModeToggle {
93+
position: absolute;
94+
right: 91px;
95+
96+
&.hasTadaIcon {
97+
right: 149px;
98+
}
99+
100+
svg {
101+
path {
102+
fill: var(--theme-node-sync-icon-color);
103+
}
104+
}
105+
}
106+
107+
.rectangle {
108+
&.hasTadaIcon {
109+
right: 220px;
110+
}
111+
112+
background-color: var(--theme-node-sync-icon-color);
113+
height: 12px;
114+
opacity: 0.3;
115+
position: absolute;
116+
right: 162px;
117+
width: 1px;
118+
}
91119
}

source/renderer/app/components/widgets/NodeSyncStatusIcon.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
.component {
22
overflow: visible;
33
position: absolute;
4-
right: 100px;
4+
right: 202px;
55

66
&.hasTadaIcon {
7-
right: 162px;
7+
right: 260px;
88
}
99

1010
&:hover {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// @flow
2+
import React from 'react';
3+
import SVGInline from 'react-svg-inline';
4+
import classNames from 'classnames';
5+
import { PopOver } from 'react-polymorph/lib/components/PopOver';
6+
import { intlShape, injectIntl } from 'react-intl';
7+
import revealIcon from '../../../assets/images/reveal-key.inline.svg';
8+
import hideIcon from '../../../assets/images/hide-key.inline.svg';
9+
import styles from './DiscreetToggle.scss';
10+
import { messages } from './DiscreetToggle.messages';
11+
12+
type Props = {
13+
className?: string,
14+
intl: intlShape.isRequired,
15+
isDiscreetMode?: Boolean,
16+
onToggle: Function,
17+
};
18+
19+
const DiscreetToggle = ({
20+
className,
21+
intl,
22+
isDiscreetMode = true,
23+
onToggle,
24+
}: Props) => {
25+
return (
26+
<div className={classNames(styles.root, className)}>
27+
<PopOver
28+
content={
29+
<span className={styles.tooltip}>
30+
{intl.formatMessage(
31+
messages[isDiscreetMode ? 'discreetModeOff' : 'discreetModeOn']
32+
)}
33+
</span>
34+
}
35+
>
36+
<button className={styles.button} onClick={onToggle}>
37+
<SVGInline
38+
svg={isDiscreetMode ? hideIcon : revealIcon}
39+
className={classNames(
40+
styles.icon,
41+
isDiscreetMode && styles.hideIcon
42+
)}
43+
/>
44+
</button>
45+
</PopOver>
46+
</div>
47+
);
48+
};
49+
50+
export default injectIntl(DiscreetToggle);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @flow
2+
import { defineMessages } from 'react-intl';
3+
4+
export const messages = defineMessages({
5+
discreetModeOn: {
6+
id: 'widgets.discreetToggle.on',
7+
defaultMessage: '!!!Toggle discreet mode on',
8+
description:
9+
'Text for the tooltip on "discreet mode" button when mode is on',
10+
},
11+
discreetModeOff: {
12+
id: 'widgets.discreetToggle.off',
13+
defaultMessage: '!!!Toggle discreet mode off',
14+
description:
15+
'Text for the tooltip on "discreet mode" button when mode is off',
16+
},
17+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.root {
2+
.button {
3+
border-radius: 50%;
4+
cursor: pointer;
5+
height: 44px;
6+
opacity: 0.4;
7+
width: 44px;
8+
9+
&:hover {
10+
background-color: var(
11+
--theme-news-feed-icon-toggle-hover-background-color
12+
);
13+
opacity: 0.8;
14+
}
15+
}
16+
17+
.icon {
18+
svg {
19+
height: 15px;
20+
width: 21px;
21+
}
22+
23+
&.hideIcon {
24+
svg {
25+
height: 18px;
26+
}
27+
}
28+
}
29+
}
30+
31+
.tooltip {
32+
font-family: var(--font-light);
33+
font-size: 14px;
34+
}
Lines changed: 110 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// @flow
2-
import React, { Component } from 'react';
2+
import React from 'react';
33
import { observer, inject } from 'mobx-react';
4+
import classnames from 'classnames';
45
import TopBar from '../components/layout/TopBar';
56
import NodeSyncStatusIcon from '../components/widgets/NodeSyncStatusIcon';
7+
import DiscreetToggle from '../components/widgets/discreet-mode/DiscreetToggle';
68
import NewsFeedIcon from '../components/widgets/NewsFeedIcon';
79
import TadaButton from '../components/widgets/TadaButton';
810
import WalletTestEnvironmentLabel from '../components/widgets/WalletTestEnvironmentLabel';
@@ -12,109 +14,121 @@ import menuIconClosed from '../assets/images/menu-ic.inline.svg';
1214
import { matchRoute } from '../utils/routing';
1315
import { ROUTES } from '../routes-config';
1416
import { IS_TADA_ICON_AVAILABLE } from '../config/topBarConfig';
17+
import topBarStyles from '../components/layout/TopBar.scss';
18+
import { useDiscreetModeFeature } from '../features/discreet-mode';
1519

16-
type Props = InjectedProps;
20+
const TopBarContainer = (
21+
{ actions, stores }: InjectedProps = { actions: null, stores: null }
22+
) => {
23+
const {
24+
sidebar,
25+
app,
26+
networkStatus,
27+
wallets,
28+
newsFeed,
29+
appUpdate,
30+
staking,
31+
} = stores;
32+
const {
33+
isSynced,
34+
syncPercentage,
35+
isShelleyActivated,
36+
isAlonzoActivated,
37+
isAlonzoPending,
38+
} = networkStatus;
39+
const { stakingInfoWasOpen } = staking;
40+
const shouldShowTadaIconAnimation = isAlonzoActivated && !stakingInfoWasOpen;
41+
const shouldShowTadaIcon =
42+
IS_TADA_ICON_AVAILABLE && (isAlonzoPending || isAlonzoActivated);
1743

18-
@inject('stores', 'actions')
19-
@observer
20-
export default class TopBarContainer extends Component<Props> {
21-
static defaultProps = { actions: null, stores: null };
44+
const { active, isWalletRoute, hasAnyWallets, hasRewardsWallets } = wallets;
45+
const {
46+
currentRoute,
47+
environment: { isMainnet, network },
48+
openExternalLink,
49+
} = app;
50+
const walletRoutesMatch = matchRoute(
51+
`${ROUTES.WALLETS.ROOT}/:id(*page)`,
52+
currentRoute
53+
);
54+
const showSubMenuToggle = isWalletRoute && hasAnyWallets;
55+
const activeWallet = walletRoutesMatch && active != null ? active : null;
56+
const leftIconSVG = sidebar.isShowingSubMenus
57+
? menuIconOpened
58+
: menuIconClosed;
59+
const leftIcon = showSubMenuToggle ? leftIconSVG : null;
60+
const testnetLabel = !isMainnet ? (
61+
<WalletTestEnvironmentLabel network={network} />
62+
) : null;
2263

23-
render() {
24-
const { actions, stores } = this.props;
25-
const {
26-
sidebar,
27-
app,
28-
networkStatus,
29-
wallets,
30-
newsFeed,
31-
appUpdate,
32-
staking,
33-
} = stores;
34-
const {
35-
isSynced,
36-
syncPercentage,
37-
isShelleyActivated,
38-
isAlonzoActivated,
39-
isAlonzoPending,
40-
} = networkStatus;
41-
const { stakingInfoWasOpen } = staking;
42-
const shouldShowTadaIconAnimation =
43-
isAlonzoActivated && !stakingInfoWasOpen;
44-
const shouldShowTadaIcon =
45-
IS_TADA_ICON_AVAILABLE && (isAlonzoPending || isAlonzoActivated);
64+
const onWalletAdd = () => {
65+
actions.router.goToRoute.trigger({
66+
route: ROUTES.WALLETS.ADD,
67+
});
68+
};
4669

47-
const { active, isWalletRoute, hasAnyWallets, hasRewardsWallets } = wallets;
48-
const {
49-
currentRoute,
50-
environment: { isMainnet, network },
51-
openExternalLink,
52-
} = app;
53-
const walletRoutesMatch = matchRoute(
54-
`${ROUTES.WALLETS.ROOT}/:id(*page)`,
55-
currentRoute
56-
);
57-
const showSubMenuToggle = isWalletRoute && hasAnyWallets;
58-
const activeWallet = walletRoutesMatch && active != null ? active : null;
59-
const leftIconSVG = sidebar.isShowingSubMenus
60-
? menuIconOpened
61-
: menuIconClosed;
62-
const leftIcon = showSubMenuToggle ? leftIconSVG : null;
63-
const testnetLabel = !isMainnet ? (
64-
<WalletTestEnvironmentLabel network={network} />
65-
) : null;
70+
const onClickTadaButton = () => {
71+
actions.router.goToRoute.trigger({
72+
route: ROUTES.STAKING.INFO,
73+
});
74+
};
6675

67-
const onWalletAdd = () => {
68-
actions.router.goToRoute.trigger({
69-
route: ROUTES.WALLETS.ADD,
70-
});
71-
};
76+
const onTransferFunds = (sourceWalletId: string) =>
77+
actions.wallets.transferFundsSetSourceWalletId.trigger({
78+
sourceWalletId,
79+
});
7280

73-
const onClickTadaButton = () => {
74-
actions.router.goToRoute.trigger({
75-
route: ROUTES.STAKING.INFO,
76-
});
77-
};
81+
const { unread } = newsFeed.newsFeedData;
82+
const { displayAppUpdateNewsItem } = appUpdate;
7883

79-
const onTransferFunds = (sourceWalletId: string) =>
80-
actions.wallets.transferFundsSetSourceWalletId.trigger({
81-
sourceWalletId,
82-
});
84+
const hasUnreadNews = unread.length > 0;
8385

84-
const { unread } = newsFeed.newsFeedData;
85-
const { displayAppUpdateNewsItem } = appUpdate;
86+
const discreetModeFeature = useDiscreetModeFeature();
8687

87-
const hasUnreadNews = unread.length > 0;
88-
89-
return (
90-
<TopBar
91-
leftIcon={leftIcon}
92-
onLeftIconClick={actions.sidebar.toggleSubMenus.trigger}
93-
activeWallet={activeWallet}
94-
onTransferFunds={onTransferFunds}
95-
hasRewardsWallets={hasRewardsWallets}
96-
onWalletAdd={onWalletAdd}
97-
onLearnMore={openExternalLink}
98-
isShelleyActivated={isShelleyActivated}
99-
>
100-
{testnetLabel}
101-
<NodeSyncStatusIcon
102-
isSynced={isSynced}
103-
syncPercentage={syncPercentage}
104-
hasTadaIcon={shouldShowTadaIcon}
105-
/>
106-
{shouldShowTadaIcon && (
107-
<TadaButton
108-
onClick={onClickTadaButton}
109-
shouldAnimate={shouldShowTadaIconAnimation}
110-
/>
88+
return (
89+
<TopBar
90+
leftIcon={leftIcon}
91+
onLeftIconClick={actions.sidebar.toggleSubMenus.trigger}
92+
activeWallet={activeWallet}
93+
onTransferFunds={onTransferFunds}
94+
hasRewardsWallets={hasRewardsWallets}
95+
onWalletAdd={onWalletAdd}
96+
onLearnMore={openExternalLink}
97+
isShelleyActivated={isShelleyActivated}
98+
>
99+
{testnetLabel}
100+
<NodeSyncStatusIcon
101+
isSynced={isSynced}
102+
syncPercentage={syncPercentage}
103+
hasTadaIcon={shouldShowTadaIcon}
104+
/>
105+
<span
106+
className={classnames(
107+
topBarStyles.rectangle,
108+
shouldShowTadaIcon && topBarStyles.hasTadaIcon
111109
)}
112-
<NewsFeedIcon
113-
onNewsFeedIconClick={actions.app.toggleNewsFeed.trigger}
114-
hasNotification={hasUnreadNews}
115-
hasUpdate={displayAppUpdateNewsItem}
110+
/>
111+
<DiscreetToggle
112+
className={classnames(
113+
topBarStyles.discreetModeToggle,
114+
shouldShowTadaIcon && topBarStyles.hasTadaIcon
115+
)}
116+
isDiscreetMode={discreetModeFeature.isDiscreetMode}
117+
onToggle={discreetModeFeature.toggleDiscreetMode}
118+
/>
119+
{shouldShowTadaIcon && (
120+
<TadaButton
121+
onClick={onClickTadaButton}
122+
shouldAnimate={shouldShowTadaIconAnimation}
116123
/>
117-
</TopBar>
118-
);
119-
}
120-
}
124+
)}
125+
<NewsFeedIcon
126+
onNewsFeedIconClick={actions.app.toggleNewsFeed.trigger}
127+
hasNotification={hasUnreadNews}
128+
hasUpdate={displayAppUpdateNewsItem}
129+
/>
130+
</TopBar>
131+
);
132+
};
133+
134+
export default inject('stores', 'actions')(observer(TopBarContainer));

0 commit comments

Comments
 (0)