Skip to content

Commit 19fc890

Browse files
authored
feat: 🎉 support unicode gitmojis
Add toggle to switch between shortcode and unicode gitmojis closes #9
1 parent 8884146 commit 19fc890

13 files changed

+421
-242
lines changed

components/common/recent-list-item.component.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const styles = (theme: CommitComposerTheme) => ({
1212
itemContainer: {
1313
minHeight: 25,
1414
minWidth: 25,
15-
padding: 10,
15+
padding: '5px 10px',
1616
'&:hover': {
1717
backgroundColor: theme.itemHoverBG,
1818
cursor: 'pointer',
@@ -24,6 +24,7 @@ const styles = (theme: CommitComposerTheme) => ({
2424
});
2525

2626
export interface OwnProps {
27+
itemClassName?: string;
2728
item: string;
2829
title: string;
2930
display?: JSX.Element;
@@ -36,11 +37,13 @@ export interface State {}
3637

3738
class RecentListItemComponent extends React.Component<Props, State> {
3839
render(): JSX.Element {
39-
const { classes, display, item, title, onClick } = this.props;
40+
const { classes, display, item, itemClassName, title, onClick } = this.props;
4041

4142
return (
4243
<Tooltip overlayClassName={classes.tooltip} title={title} mouseLeaveDelay={0}>
43-
<Col className={classNames(classes.itemContainer)} onClick={() => onClick?.(item)}>
44+
<Col
45+
className={classNames(classes.itemContainer, itemClassName)}
46+
onClick={() => onClick?.(item)}>
4447
<Row className={classes.center}>{display}</Row>
4548
</Col>
4649
</Tooltip>

components/common/recent-list.component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ const styles = {
2121
},
2222
itemRow: {
2323
overflow: 'hidden',
24-
maxHeight: 42,
24+
maxHeight: 32,
2525
},
2626
};
2727

2828
export interface OwnProps {
2929
className?: string;
30+
itemClassName?: string;
3031
onClick?: (item: string) => void;
3132
items: RecentItem[];
3233
}
@@ -37,7 +38,7 @@ export interface State {}
3738

3839
class RecentListComponent extends React.Component<Props, State> {
3940
render(): JSX.Element {
40-
const { classes, items, className, onClick } = this.props;
41+
const { classes, items, className, itemClassName, onClick } = this.props;
4142

4243
return items && items.length ? (
4344
<Row className={classNames(classes.root, className)}>
@@ -46,6 +47,7 @@ class RecentListComponent extends React.Component<Props, State> {
4647
<Row className={classes.itemRow}>
4748
{items.map((x) => (
4849
<RecentListItemComponent
50+
itemClassName={itemClassName}
4951
key={x.item}
5052
item={x.item}
5153
title={x.title}

components/common/searchable-menu-item.component.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import { Col, Row } from 'antd';
22
import React from 'react';
33
import withStyles, { WithStylesProps } from 'react-jss';
44

5-
const styles = {
5+
const styles = (theme: CommitComposerTheme) => ({
66
root: {
77
whiteSpace: 'nowrap',
88
padding: '9px',
99
flexWrap: 'nowrap',
1010
'&:hover': {
11-
backgroundColor: '#f5f5f5',
11+
backgroundColor: theme.itemHoverBG,
1212
cursor: 'pointer',
1313
},
1414
},
15-
};
15+
});
1616

1717
export interface OwnProps {
1818
item: string;

components/common/searchable-menu.component.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,7 @@ const styles = (theme: CommitComposerTheme) => ({
3434
fontSize: 12,
3535
paddingRight: 9,
3636
},
37-
searchRow: {
38-
padding: 9,
39-
},
37+
searchRow: {},
4038
itemRow: {
4139
overflowY: 'auto',
4240
overflowX: 'hidden',
@@ -51,6 +49,7 @@ const styles = (theme: CommitComposerTheme) => ({
5149
});
5250

5351
export interface OwnProps {
52+
searchBarClassName?: string;
5453
className?: string;
5554
onClick?: (item: string) => void;
5655
focus: boolean;
@@ -172,12 +171,12 @@ class SearchableMenuComponent extends React.Component<Props, State> {
172171
}
173172

174173
render(): JSX.Element {
175-
const { classes, className } = this.props;
174+
const { classes, className, searchBarClassName, children } = this.props;
176175
const { visibleItems } = this.state;
177176

178177
return (
179178
<div className={classNames(classes.root, className)}>
180-
<Row className={classes.searchRow}>
179+
<Row className={classNames(classes.searchRow, searchBarClassName)}>
181180
<span className="ant-input-affix-wrapper">
182181
<Input
183182
placeholder="Search"
@@ -218,6 +217,9 @@ class SearchableMenuComponent extends React.Component<Props, State> {
218217
))}
219218
</Col>
220219
</Row>
220+
<Row onClick={(e) => e.stopPropagation()}>
221+
<Col flex="auto">{children}</Col>
222+
</Row>
221223
</div>
222224
);
223225
}

components/editor/gitmoji-picker.component.tsx

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Button, Dropdown } from 'antd';
1+
import { Button, Dropdown, Space, Switch, Typography } from 'antd';
22
import classNames from 'classnames';
33
import RecentListComponent from 'components/common/recent-list.component';
44
import SearchableMenuComponent from 'components/common/searchable-menu.component';
55
import React from 'react';
6-
import { AiOutlineDown } from 'react-icons/ai';
6+
import { AiOutlineCheck, AiOutlineClose, AiOutlineDown } from 'react-icons/ai';
77
import withStyles, { WithStylesProps } from 'react-jss';
88
import { connect, Dispatch } from 'react-redux';
99
import { GitmojiDefinition, GITMOJIS } from 'shared/presets/gitmojis';
1010
import { AppState, EditorState } from 'state';
1111

12-
import { GitmojiSelectAction } from './state/editor.action';
12+
import { GitmojiSelectAction, ToggleShortcodeAction } from './state/editor.action';
1313

1414
const styles = (theme: CommitComposerTheme) => ({
1515
menu: {
@@ -60,8 +60,30 @@ const styles = (theme: CommitComposerTheme) => ({
6060
minWidth: 'unset',
6161
},
6262
},
63+
searchBar: {
64+
backgroundColor: theme.lighter,
65+
padding: 9,
66+
},
67+
noTopPadding: {
68+
paddingTop: 0,
69+
},
6370
recentList: {
6471
maxHeight: 70,
72+
backgroundColor: theme.lighter,
73+
},
74+
recentItem: {
75+
'&:hover': {
76+
backgroundColor: theme.itemHoverBG,
77+
},
78+
},
79+
actionContainer: {
80+
padding: '4px 9px',
81+
justifyContent: 'flex-end',
82+
width: '100%',
83+
backgroundColor: theme.lighter,
84+
},
85+
actionText: {
86+
fontSize: 12,
6587
},
6688
});
6789

@@ -71,6 +93,7 @@ export interface ReduxProps {
7193
}
7294
export interface DispatchProps {
7395
gitmojiSelected: (gitmoji: GitmojiDefinition) => void;
96+
toggleShortcode: (value: boolean) => void;
7497
}
7598
type Props = WithStylesProps<typeof styles> & OwnProps & ReduxProps & DispatchProps;
7699
export interface State {
@@ -106,12 +129,13 @@ class GitmojiPickerComponent extends React.Component<Props, State> {
106129
}
107130

108131
render(): JSX.Element {
109-
const { classes, editor } = this.props;
132+
const { classes, editor, toggleShortcode } = this.props;
110133
const { hovered, visible } = this.state;
111134

112135
const menu = (
113136
<span className={classes.menu}>
114137
<RecentListComponent
138+
itemClassName={classes.recentItem}
115139
className={classes.recentList}
116140
onClick={(key) => this.handleClick(key)}
117141
items={editor.recentGitmojis.map((x) => ({
@@ -127,6 +151,9 @@ class GitmojiPickerComponent extends React.Component<Props, State> {
127151
<SearchableMenuComponent
128152
focus={visible}
129153
className={classes.items}
154+
searchBarClassName={classNames(classes.searchBar, {
155+
[classes.noTopPadding]: Boolean(editor.recentGitmojis?.length),
156+
})}
130157
onClick={(key) => this.handleClick(key)}
131158
items={GITMOJIS.map((x) => ({
132159
item: x.shortcode,
@@ -137,8 +164,18 @@ class GitmojiPickerComponent extends React.Component<Props, State> {
137164
{x.icon}
138165
</span>
139166
),
140-
}))}
141-
/>
167+
}))}>
168+
<Space className={classes.actionContainer}>
169+
<Typography.Text className={classes.actionText}>Shortcode:</Typography.Text>
170+
<Switch
171+
size="small"
172+
defaultChecked={editor.useShortcode}
173+
checkedChildren={<AiOutlineCheck />}
174+
unCheckedChildren={<AiOutlineClose />}
175+
onChange={(x) => toggleShortcode(x)}
176+
/>
177+
</Space>
178+
</SearchableMenuComponent>
142179
</span>
143180
);
144181

@@ -178,6 +215,7 @@ function mapStateToProps(state: AppState): ReduxProps {
178215
function mapDispatchToProps(dispatch: Dispatch): DispatchProps {
179216
return {
180217
gitmojiSelected: (gitmoji) => dispatch(GitmojiSelectAction.get(gitmoji)),
218+
toggleShortcode: (value) => dispatch(ToggleShortcodeAction.get(value)),
181219
};
182220
}
183221

components/editor/state/editor.action.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export const EditorFormatAction = defineAction('EditorFormatAction');
1111
export const EditorLoadAction = defineAction<boolean>('EditorLoadAction');
1212
export const GitmojiSelectAction = defineAction<GitmojiDefinition>('GitmojiSelectAction');
1313
export const TypeSelectAction = defineAction<TypeDefinition>('TypeSelectAction');
14+
export const ToggleShortcodeAction = defineAction<boolean>('ToggleShortcodeAction');

components/editor/state/editor.reducer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
EditorLoadAction,
1111
EditorUpdatedAction,
1212
GitmojiSelectAction,
13+
ToggleShortcodeAction,
1314
TypeSelectAction,
1415
ValidationUpdatedAsync,
1516
} from './editor.action';
@@ -36,7 +37,7 @@ const editorReducer = (
3637
state.loading = action.payload;
3738
} else if (GitmojiSelectAction.is(action)) {
3839
const { payload } = action;
39-
state.editorValue = CommitMessageLib.setGitmoji(state.editorValue, payload);
40+
state.editorValue = CommitMessageLib.setGitmoji(state.editorValue, payload, state.useShortcode);
4041

4142
const map = state.recentGitmojis.map((x) => ({ key: x.shortcode, value: x }));
4243
const cache = new LRUCache<GitmojiDefinition>(map, 20);
@@ -50,6 +51,8 @@ const editorReducer = (
5051
const cache = new LRUCache<TypeDefinition>(map, 20);
5152
cache.write(payload.key, payload);
5253
state.recentTypes = cache.toArray();
54+
} else if (ToggleShortcodeAction.is(action)) {
55+
state.useShortcode = action.payload;
5356
}
5457

5558
return state;

components/editor/type-picker.component.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,21 @@ const styles = (theme: CommitComposerTheme) => ({
4848
minWidth: 'unset',
4949
},
5050
},
51+
searchBar: {
52+
backgroundColor: theme.lighter,
53+
padding: 9,
54+
},
55+
noTopPadding: {
56+
paddingTop: 0,
57+
},
5158
recentList: {
5259
maxHeight: 70,
60+
backgroundColor: theme.lighter,
61+
},
62+
recentItem: {
63+
'&:hover': {
64+
backgroundColor: theme.itemHoverBG,
65+
},
5366
},
5467
});
5568

@@ -100,6 +113,7 @@ class TypePickerComponent extends React.Component<Props, State> {
100113
const menu = (
101114
<span className={classes.menu}>
102115
<RecentListComponent
116+
itemClassName={classes.recentItem}
103117
className={classes.recentList}
104118
onClick={(key) => this.handleClick(key)}
105119
items={editor.recentTypes.map((x) => ({
@@ -111,6 +125,9 @@ class TypePickerComponent extends React.Component<Props, State> {
111125
<SearchableMenuComponent
112126
focus={visible}
113127
className={classes.items}
128+
searchBarClassName={classNames(classes.searchBar, {
129+
[classes.noTopPadding]: Boolean(editor.recentTypes?.length),
130+
})}
114131
onClick={(key) => this.handleClick(key)}
115132
items={TYPES.map((x) => ({
116133
item: x.key,

0 commit comments

Comments
 (0)