Skip to content

Commit

Permalink
feat(giphy): add first giphy integration
Browse files Browse the repository at this point in the history
  • Loading branch information
ph1p committed Nov 3, 2021
1 parent 0d30310 commit 0f9334e
Show file tree
Hide file tree
Showing 13 changed files with 953 additions and 127 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Figma Chat ![](https://github.com/ph1p/figma-chat/workflows/Build%20Figma-Chat/badge.svg)

![](https://raw.githubusercontent.com/ph1p/figma-chat/master/assets/header.png)
<img width="960" alt="header" src="https://user-images.githubusercontent.com/15351728/140192961-8155d6f9-e9ab-4be3-bbb4-7e41df666d56.png">

## Monorepo

Expand Down
2 changes: 2 additions & 0 deletions packages/plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"license": "ISC",
"dependencies": {
"@fc/shared": "link:../shared/src",
"@giphy/js-fetch-api": "^4.1.2",
"@giphy/react-components": "^5.4.0",
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
"linkify-react": "^3.0.3",
Expand Down
266 changes: 161 additions & 105 deletions packages/plugin/src/views/Chat/components/Chatbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import EmojiIcon from '@fc/shared/assets/icons/EmojiIcon';
import GearIcon from '@fc/shared/assets/icons/GearIcon';
import SendArrowIcon from '@fc/shared/assets/icons/SendArrowIcon';
import { CustomLink } from '@fc/shared/components/CustomLink';
import { GiphyGrid } from '@fc/shared/components/GiphyGrid';
import Tooltip, { RefTooltip } from '@fc/shared/components/Tooltip';
import { ConnectionEnum } from '@fc/shared/utils/interfaces';

Expand Down Expand Up @@ -49,120 +50,175 @@ const ChatBar: FunctionComponent<ChatProps> = (props) => {
[]
);

useEffect(() => {}, [props.textMessage]);

const sendMessage = (e) => {
props.sendMessage(e);
chatTextInput.current.value = '';
e.preventDefault();
if (!chatTextInput.current.value.startsWith('/giphy')) {
props.sendMessage(e);
chatTextInput.current.value = '';
}
};

return (
<ChatBarForm isSettings={Boolean(isSettings)} onSubmit={sendMessage}>
<ConnectionInfo isConnected={isConnected}>
{isFailed ? 'connection failed 🙈' : 'connecting...'}
</ConnectionInfo>

<ChatInputWrapper>
<RefTooltip hover ref={selectionTooltipRef} handler={selectionRef}>
Add selection ({store.selectionCount} elements)
</RefTooltip>
<SettingsAndUsers>
<CustomLink to="/settings">
<div className={`gear ${store.settings.isDarkTheme ? 'dark' : ''}`}>
<GearIcon />
</div>
</CustomLink>
{store.status === ConnectionEnum.CONNECTED && (
<CustomLink to="/user-list">
<Users>
<UserChips>
{store.online
.filter((_, i) => i < 2)
.map((user) => (
<Chip
key={user.id}
style={{
backgroundColor: user.color,
backgroundImage: !user?.avatar
? `url(${user.photoUrl})`
: undefined,
}}
>
{user?.avatar || ''}
</Chip>
))}
{store.online.length > 2 && (
<Chip>+{store.online.length - 2}</Chip>
)}
</UserChips>
</Users>
<>
<GiphyGrid
store={store}
setTextMessage={(p) => {
props.setTextMessage(p);
chatTextInput.current.value = '';
}}
textMessage={props.textMessage}
/>
<ChatBarForm isSettings={Boolean(isSettings)} onSubmit={sendMessage}>
<ConnectionInfo isConnected={isConnected}>
{isFailed ? 'connection failed 🙈' : 'connecting...'}
</ConnectionInfo>

<ChatInputWrapper>
<RefTooltip hover ref={selectionTooltipRef} handler={selectionRef}>
Add selection ({store.selectionCount} elements)
</RefTooltip>
<SettingsAndUsers>
<CustomLink to="/settings">
<div
className={`gear ${store.settings.isDarkTheme ? 'dark' : ''}`}
>
<GearIcon />
</div>
</CustomLink>
)}
</SettingsAndUsers>

<ChatInput isConnected={isConnected}>
<input
ref={chatTextInput}
type="input"
onChange={({ target }: any) =>
props.setTextMessage(target.value.substr(0, 1000))
}
placeholder={`Write something ... ${
props.selectionIsChecked ? '(optional)' : ''
}`}
/>

<Tooltip
ref={emojiPickerRef}
style={{
paddingTop: 11,
paddingBottom: 11,
paddingLeft: 17,
paddingRight: 17,
}}
handler={React.forwardRef((p, ref) => (
<EmojiPickerStyled {...p} ref={ref}>
<EmojiIcon />
</EmojiPickerStyled>
))}
>
<EmojiList>
{['😂', '😊', '👍', '🙈', '🔥', '🤔', '💩'].map((emoji) => (
<span
key={emoji}
data-emoji={emoji}
onClick={(e) => {
props.setTextMessage(emoji);
sendMessage(e);
emojiPickerRef.current.hide();
}}
/>
{store.status === ConnectionEnum.CONNECTED && (
<CustomLink to="/user-list">
<Users>
<UserChips>
{store.online
.filter((_, i) => i < 2)
.map((user) => (
<Chip
key={user.id}
style={{
backgroundColor: user.color,
backgroundImage: !user?.avatar
? `url(${user.photoUrl})`
: undefined,
}}
>
{user?.avatar || ''}
</Chip>
))}
{store.online.length > 2 && (
<Chip>+{store.online.length - 2}</Chip>
)}
</UserChips>
</Users>
</CustomLink>
)}
</SettingsAndUsers>

<ChatInput isConnected={isConnected}>
<input
ref={chatTextInput}
type="input"
onChange={({ target }: any) =>
props.setTextMessage(target.value.substr(0, 1000))
}
placeholder={`Write something ... ${
props.selectionIsChecked ? '(optional)' : ''
}`}
/>

<Tooltip
ref={emojiPickerRef}
style={{
paddingTop: 11,
paddingBottom: 11,
paddingLeft: 17,
paddingRight: 17,
}}
handler={React.forwardRef((p, ref) => (
<EmojiPickerStyled {...p} ref={ref}>
<EmojiIcon />
</EmojiPickerStyled>
))}
</EmojiList>
</Tooltip>

<SelectionCheckbox
ref={selectionRef}
color={store.settings.color}
checked={props.selectionIsChecked}
hasSelection={hasSelection}
onMouseEnter={() => selectionTooltipRef.current.show()}
onMouseLeave={() => selectionTooltipRef.current.hide()}
onClick={() => {
props.setSelectionIsChecked(!props.selectionIsChecked);
chatTextInput.current.focus();
}}
>
<div>{store.selectionCount < 10 && store.selectionCount}</div>
</SelectionCheckbox>

<SendButton color={store.settings.color} onClick={sendMessage}>
<SendArrowIcon />
</SendButton>
</ChatInput>
</ChatInputWrapper>
</ChatBarForm>
>
<EmojiList>
{['😂', '😊', '👍', '🙈', '🔥', '🤔', '💩'].map((emoji) => (
<span
key={emoji}
data-emoji={emoji}
onClick={(e) => {
props.setTextMessage(emoji);
sendMessage(e);
emojiPickerRef.current.hide();
}}
/>
))}
</EmojiList>
</Tooltip>

<SelectionCheckbox
ref={selectionRef}
color={store.settings.color}
checked={props.selectionIsChecked}
hasSelection={hasSelection}
onMouseEnter={() => selectionTooltipRef.current.show()}
onMouseLeave={() => selectionTooltipRef.current.hide()}
onClick={() => {
props.setSelectionIsChecked(!props.selectionIsChecked);
chatTextInput.current.focus();
}}
>
<div>{store.selectionCount < 10 && store.selectionCount}</div>
</SelectionCheckbox>

<SendButton color={store.settings.color} onClick={sendMessage}>
<SendArrowIcon />
</SendButton>
</ChatInput>
</ChatInputWrapper>
</ChatBarForm>
</>
);
};

const GiphyHeader = styled.div`
display: flex;
padding: 4px 5px 12px;
.logo {
svg {
width: 70px;
height: 15px;
}
}
.searchterm {
color: #4c4c4c;
margin-left: 6px;
}
`;
const Giphy = styled.div`
position: absolute;
bottom: 54px;
left: 9px;
width: 315px;
height: 250px;
overflow: auto;
background-color: #000;
border-radius: 14px;
padding: 9px;
.overlay {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: rgba(0, 0, 0, 0.4);
}
}
`;

const Users = styled.div`
display: flex;
align-items: center;
Expand Down
1 change: 1 addition & 0 deletions packages/plugin/src/views/Chat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const Chat: FunctionComponent = observer(() => {
if (e) {
e.preventDefault();
}

if (store.roomName) {
let data = {
text: chatState.textMessage,
Expand Down
28 changes: 28 additions & 0 deletions packages/shared/src/assets/GiphyLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { FunctionComponent } from 'react';

export const GiphyLogo: FunctionComponent = () => (
<svg
height="534"
width="2500"
xmlns="https://www.w3.org/2000/svg"
viewBox="0 0 163.79999999999998 35"
>
<g fill="none" fillRule="evenodd">
<path d="M4 4h20v27H4z" fill="#000" />
<g fillRule="nonzero">
<path d="M0 3h4v29H0z" fill="#04ff8e" />
<path d="M24 11h4v21h-4z" fill="#8e2eff" />
<path d="M0 31h28v4H0z" fill="#00c5ff" />
<path d="M0 0h16v4H0z" fill="#fff152" />
<path d="M24 8V4h-4V0h-4v12h12V8" fill="#ff5b5b" />
<path d="M24 16v-4h4" fill="#551c99" />
</g>
<path d="M16 0v4h-4" fill="#999131" />
<path
d="M59.1 12c-2-1.9-4.4-2.4-6.2-2.4-4.4 0-7.3 2.6-7.3 8 0 3.5 1.8 7.8 7.3 7.8 1.4 0 3.7-.3 5.2-1.4v-3.5h-6.9v-6h13.3v12.1c-1.7 3.5-6.4 5.3-11.7 5.3-10.7 0-14.8-7.2-14.8-14.3S42.7 3.2 52.9 3.2c3.8 0 7.1.8 10.7 4.4zm9.1 19.2V4h7.6v27.2zm20.1-7.4v7.3h-7.7V4h13.2c7.3 0 10.9 4.6 10.9 9.9 0 5.6-3.6 9.9-10.9 9.9zm0-6.5h5.5c2.1 0 3.2-1.6 3.2-3.3 0-1.8-1.1-3.4-3.2-3.4h-5.5zM125 31.2V20.9h-9.8v10.3h-7.7V4h7.7v10.3h9.8V4h7.6v27.2zm24.2-17.9l5.9-9.3h8.7v.3l-10.8 16v10.8h-7.7V20.3L135 4.3V4h8.7z"
fill="#fff"
fillRule="nonzero"
/>
</g>
</svg>
);
20 changes: 20 additions & 0 deletions packages/shared/src/assets/icons/GiphyCloseIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { FunctionComponent } from 'react';

export const GiphyCloseIcon: FunctionComponent = () => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0 12C0 5.37258 5.37258 0 12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12Z"
fill="white"
/>
<path
d="M8 15.548L8.95198 16.5L12.0028 13.4492L15.0536 16.5L16 15.5536L12.9492 12.5028L16 9.45198L15.048 8.5L11.9972 11.5508L8.94642 8.5L8 9.44642L11.0508 12.4972L8 15.548Z"
fill="black"
/>
</svg>
);
Loading

0 comments on commit 0f9334e

Please sign in to comment.