From b01fe05cd7dc2c030d2d6b0719b1481525627555 Mon Sep 17 00:00:00 2001 From: ph1p Date: Fri, 1 May 2020 17:06:53 +0200 Subject: [PATCH] feat(page-change): add the ability to change the page on selection --- src/code.ts | 42 ++++++++++++++++++++++++++++++++---- src/components/Chatbar.tsx | 32 ++++++++------------------- src/components/Message.tsx | 44 ++++++++++++++++++++++++++++++-------- src/store/index.tsx | 12 ++++++++++- src/views/Chat.tsx | 22 +++++++++++++------ 5 files changed, 108 insertions(+), 44 deletions(-) diff --git a/src/code.ts b/src/code.ts index 9c1ee9c..2654ea4 100644 --- a/src/code.ts +++ b/src/code.ts @@ -52,10 +52,15 @@ async function main() { figma.root.setPluginData('history', history); } + // Parse History + try { + history = typeof history === 'string' ? JSON.parse(history) : [] + } catch { } + return { roomName, secret, - history: typeof history === 'string' ? JSON.parse(history) : [], + history, instanceId, }; } @@ -71,7 +76,13 @@ const getSelectionIds = () => { }; const sendSelection = () => { - postMessage('selection', getSelectionIds()); + postMessage('selection', { + page: { + id: figma.currentPage.id, + name: figma.currentPage.name + }, + nodes: getSelectionIds() + }); }; const sendRootData = async ({ roomName, secret, history, instanceId }) => { @@ -100,6 +111,13 @@ const isValidShape = (node) => node.type === 'INSTANCE' || node.type === 'POLYGON'; + +function goToPage(id) { + if (figma.getNodeById(id)) { + figma.currentPage = figma.getNodeById(id) as PageNode; + } +} + let previousSelection = figma.currentPage.selection || []; main().then(({ roomName, secret, history, instanceId }) => { @@ -198,9 +216,19 @@ main().then(({ roomName, secret, history, instanceId }) => { } break; case 'focus-nodes': + let selectedNodes = []; triggerSelectionEvent = false; + + // fallback for ids + if (message.payload.ids) { + selectedNodes = message.payload.ids + } else { + goToPage(message.payload?.page?.id); + selectedNodes = message.payload.nodes; + } + const nodes = figma.currentPage.findAll( - (n) => message.payload.ids.indexOf(n.id) !== -1 + (n) => selectedNodes.indexOf(n.id) !== -1 ); figma.currentPage.selection = nodes; @@ -217,7 +245,13 @@ main().then(({ roomName, secret, history, instanceId }) => { if (isRelaunch && !alreadyAskedForRelaunchMessage) { alreadyAskedForRelaunchMessage = true; postMessage('relaunch-message', { - selection: getSelectionIds(), + selection: { + page: { + id: figma.currentPage.id, + name: figma.currentPage.name + }, + nodes: getSelectionIds() + }, }); } break; diff --git a/src/components/Chatbar.tsx b/src/components/Chatbar.tsx index ba144ff..0c041cb 100644 --- a/src/components/Chatbar.tsx +++ b/src/components/Chatbar.tsx @@ -1,10 +1,11 @@ import React, { FunctionComponent, useState, useEffect, useRef } from 'react'; import { useRouteMatch } from 'react-router-dom'; +import { observer } from 'mobx-react'; +import { autorun } from 'mobx'; import styled from 'styled-components'; import ColorPicker from './ColorPicker'; -import { ConnectionEnum } from '../shared/interfaces'; // store -import { observer } from 'mobx-react'; import { useStore } from '../store'; +import { ConnectionEnum } from '../shared/interfaces'; interface ChatProps { sendMessage: (event: any) => void; @@ -17,25 +18,16 @@ interface ChatProps { const ChatBar: FunctionComponent = (props) => { const store = useStore(); const isSettings = useRouteMatch('/settings'); - const selection = store.selection.length; - const hasSelection = Boolean(selection); - const [show, setShow] = useState(hasSelection); + const [hasSelection, setHasSelection] = useState(false); const chatTextInput = useRef(null); const isFailed = store.status === ConnectionEnum.ERROR; const isConnected = store.status === ConnectionEnum.CONNECTED; - useEffect(() => { - if (hasSelection) { - setShow(true); - } - }, [hasSelection]); - - const onAnimationEnd = () => { - if (!hasSelection) { - setShow(false); - } - }; + useEffect( + () => autorun(() => setHasSelection(Boolean(store.selectionCount))), + [] + ); return ( = (props) => { }} > - {isFailed ? ( - <> - connection failed 🙈 - - ) : ( - 'connecting...' - )} + {isFailed ? <>connection failed 🙈 : 'connecting...'} diff --git a/src/components/Message.tsx b/src/components/Message.tsx index 66addc3..1231626 100644 --- a/src/components/Message.tsx +++ b/src/components/Message.tsx @@ -19,6 +19,9 @@ const Message: FunctionComponent = ({ data, instanceId }) => { const colorClass = colors[data.user.color] || 'blue'; const selection = data?.message?.selection; const isSelf = data.id === instanceId; + const pageName = selection?.page?.name || ''; + + const selectionCount = selection?.length || selection?.nodes?.length || 0; return ( @@ -35,16 +38,31 @@ const Message: FunctionComponent = ({ data, instanceId }) => { )} {selection ? ( - sendMainMessage('focus-nodes', { - ids: toJS(selection), - }) - } + onClick={() => { + const messageSelection = toJS(selection); + let selectionData = null; + + // fallback without page + if (messageSelection.length) { + selectionData = { + ids: messageSelection, + }; + } else { + selectionData = { + ...messageSelection, + }; + } + + sendMainMessage('focus-nodes', selectionData); + }} > - {data.message.text} + {data.message.text && ( +
{data.message.text}
+ )}
) : ( @@ -119,6 +137,14 @@ const MessageContainer = styled.div` background-color: transparent; border-color: #fff; color: #fff; + &:active { + border: 1px solid; + box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2); + } + } + + .selection-text { + margin-bottom: 10px; } &.lightblue header { @@ -188,7 +214,7 @@ const MessageContainer = styled.div` color: #1c4856; } &.purple { - background-color: #7b61ff; + background-color: #5751ff; color: #ffffff; } &.green { diff --git a/src/store/index.tsx b/src/store/index.tsx index eed9eea..bad1ba0 100644 --- a/src/store/index.tsx +++ b/src/store/index.tsx @@ -40,7 +40,17 @@ class RootStore { disableAutoScroll = false; @observable - selection = []; + selection = undefined; + + @computed + get selectionCount() { + // fallback + if (this.selection?.length) { + return this.selection.length; + } + + return this.selection?.nodes?.length || 0; + } @action scrollToBottom() { diff --git a/src/views/Chat.tsx b/src/views/Chat.tsx index af59ce9..eba44f5 100644 --- a/src/views/Chat.tsx +++ b/src/views/Chat.tsx @@ -59,7 +59,7 @@ const ChatView: FunctionComponent = (props) => { date: new Date(), }; - if (store.selection.length > 0) { + if (store.selectionCount > 0) { if (chatState.selectionIsChecked) { data = { ...data, @@ -98,8 +98,10 @@ const ChatView: FunctionComponent = (props) => { if (pmessage) { // set selection if (pmessage.type === 'selection') { - const hasSelection = pmessage.payload.length > 0; - store.selection = hasSelection ? pmessage.payload : []; + const hasSelection = + pmessage.payload?.length > 0 || pmessage.payload?.nodes?.length > 0; + + store.selection = hasSelection ? pmessage.payload : {}; if (!hasSelection) { chatState.selectionIsChecked = false; @@ -111,7 +113,10 @@ const ChatView: FunctionComponent = (props) => { roomName: dataRoomName = '', secret: dataSecret = '', history: messages = [], - selection = [], + selection = { + page: '', + nodes: [], + }, settings = {}, instanceId = '', } = { @@ -135,9 +140,12 @@ const ChatView: FunctionComponent = (props) => { if (pmessage.type === 'relaunch-message') { chatState.selectionIsChecked = true; - store.selection = pmessage.payload.selection || []; - if (store.selection.length) { + console.log(pmessage.payload.selection); + + store.selection = pmessage.payload.selection || {}; + + if (store.selectionCount) { sendMessage(); sendMainMessage('notify', 'Selection sent successfully'); } @@ -164,7 +172,7 @@ const ChatView: FunctionComponent = (props) => { <> 0} + hasSelection={store.selectionCount > 0} > {isConnected && (