From 4b711b3526d28af5501aa0084976fdc6d49cc5a6 Mon Sep 17 00:00:00 2001 From: Jordi Sala Morales Date: Tue, 4 Jun 2024 18:02:59 +0200 Subject: [PATCH] Refactor context (#139) * Refactor context * fix * fix --- ui-src/components/ExportForm.tsx | 4 +- ui-src/components/ExporterProgress.tsx | 4 +- ui-src/components/MissingFontsSection.tsx | 4 +- ui-src/components/PenpotExporter.tsx | 4 +- ui-src/components/PluginReload.tsx | 4 +- ui-src/context/FigmaContext.tsx | 111 +--------------- ui-src/context/useFigma.ts | 150 ++++++++++++++++++++++ 7 files changed, 166 insertions(+), 115 deletions(-) create mode 100644 ui-src/context/useFigma.ts diff --git a/ui-src/components/ExportForm.tsx b/ui-src/components/ExportForm.tsx index 5c963d3..1f3a889 100644 --- a/ui-src/components/ExportForm.tsx +++ b/ui-src/components/ExportForm.tsx @@ -2,14 +2,14 @@ import { Button } from '@create-figma-plugin/ui'; import { FormProvider, useForm } from 'react-hook-form'; import { Stack } from '@ui/components/Stack'; -import { useFigma } from '@ui/context'; +import { useFigmaContext } from '@ui/context'; import { MissingFontsSection } from './MissingFontsSection'; export type FormValues = Record; export const ExportForm = () => { - const { cancel, exportPenpot } = useFigma(); + const { cancel, exportPenpot } = useFigmaContext(); const methods = useForm(); return ( diff --git a/ui-src/components/ExporterProgress.tsx b/ui-src/components/ExporterProgress.tsx index ae3fded..75b3943 100644 --- a/ui-src/components/ExporterProgress.tsx +++ b/ui-src/components/ExporterProgress.tsx @@ -1,11 +1,11 @@ import { LoadingIndicator } from '@create-figma-plugin/ui'; -import { useFigma } from '@ui/context'; +import { useFigmaContext } from '@ui/context'; import { Stack } from './Stack'; export const ExporterProgress = () => { - const { currentNode, totalPages, processedPages, downloading } = useFigma(); + const { currentNode, totalPages, processedPages, downloading } = useFigmaContext(); const truncateText = (text: string, maxChars: number) => { if (text.length <= maxChars) { diff --git a/ui-src/components/MissingFontsSection.tsx b/ui-src/components/MissingFontsSection.tsx index 5c9863c..00a2acd 100644 --- a/ui-src/components/MissingFontsSection.tsx +++ b/ui-src/components/MissingFontsSection.tsx @@ -1,12 +1,12 @@ import { Banner, IconInfo32, Link, Textbox } from '@create-figma-plugin/ui'; import { Controller, useFormContext } from 'react-hook-form'; -import { useFigma } from '@ui/context'; +import { useFigmaContext } from '@ui/context'; import { Stack } from './Stack'; export const MissingFontsSection = () => { - const { missingFonts } = useFigma(); + const { missingFonts } = useFigmaContext(); if (!missingFonts || !missingFonts.length) return null; diff --git a/ui-src/components/PenpotExporter.tsx b/ui-src/components/PenpotExporter.tsx index 49b52eb..35b16ef 100644 --- a/ui-src/components/PenpotExporter.tsx +++ b/ui-src/components/PenpotExporter.tsx @@ -1,13 +1,13 @@ import { LoadingIndicator } from '@create-figma-plugin/ui'; -import { useFigma } from '@ui/context'; +import { useFigmaContext } from '@ui/context'; import { ExportForm } from './ExportForm'; import { ExporterProgress } from './ExporterProgress'; import { PluginReload } from './PluginReload'; export const PenpotExporter = () => { - const { loading, needsReload, exporting } = useFigma(); + const { loading, needsReload, exporting } = useFigmaContext(); if (loading) return ; diff --git a/ui-src/components/PluginReload.tsx b/ui-src/components/PluginReload.tsx index d20ee84..eddd03d 100644 --- a/ui-src/components/PluginReload.tsx +++ b/ui-src/components/PluginReload.tsx @@ -1,10 +1,10 @@ import { Banner, Button, IconInfo32 } from '@create-figma-plugin/ui'; import { Stack } from '@ui/components/Stack'; -import { useFigma } from '@ui/context'; +import { useFigmaContext } from '@ui/context'; export const PluginReload = () => { - const { reload, cancel } = useFigma(); + const { reload, cancel } = useFigmaContext(); return ( diff --git a/ui-src/context/FigmaContext.tsx b/ui-src/context/FigmaContext.tsx index 61c3350..3d32312 100644 --- a/ui-src/context/FigmaContext.tsx +++ b/ui-src/context/FigmaContext.tsx @@ -1,113 +1,14 @@ -import { JSX, PropsWithChildren, useEffect, useState } from 'react'; - -import { FormValues } from '@ui/components/ExportForm'; -import { parse } from '@ui/parser'; -import { PenpotDocument } from '@ui/types'; +import { JSX, PropsWithChildren } from 'react'; import { createGenericContext } from './createGenericContext'; +import { UseFigmaHook, useFigma } from './useFigma'; -type Context = { - missingFonts: string[] | undefined; - needsReload: boolean; - loading: boolean; - exporting: boolean; - downloading: boolean; - currentNode: string | undefined; - totalPages: number | undefined; - processedPages: number | undefined; - reload: () => void; - cancel: () => void; - exportPenpot: (data: FormValues) => void; -}; - -const [useFigma, StateContextProvider] = createGenericContext(); +const [useFigmaContext, StateContextProvider] = createGenericContext(); const FigmaProvider = ({ children }: PropsWithChildren): JSX.Element => { - const [missingFonts, setMissingFonts] = useState(); - const [needsReload, setNeedsReload] = useState(false); - const [loading, setLoading] = useState(true); - const [exporting, setExporting] = useState(false); - const [downloading, setDownloading] = useState(false); - const [currentNode, setCurrentNode] = useState(); - const [totalPages, setTotalPages] = useState(); - const [processedPages, setProcessedPages] = useState(); + const hook = useFigma(); - const onMessage = (event: MessageEvent<{ pluginMessage: { type: string; data: unknown } }>) => { - if (event.data.pluginMessage?.type == 'PENPOT_DOCUMENT') { - setDownloading(true); - - const document = event.data.pluginMessage.data as PenpotDocument; - const file = parse(document); - - file.export(); - } else if (event.data.pluginMessage?.type == 'CUSTOM_FONTS') { - setMissingFonts(event.data.pluginMessage.data as string[]); - setLoading(false); - setNeedsReload(false); - } else if (event.data.pluginMessage?.type == 'CHANGES_DETECTED') { - setNeedsReload(true); - } else if (event.data.pluginMessage?.type === 'PROGRESS_NODE') { - setCurrentNode(event.data.pluginMessage.data as string); - } else if (event.data.pluginMessage?.type === 'PROGRESS_TOTAL_PAGES') { - setTotalPages(event.data.pluginMessage.data as number); - setProcessedPages(0); - } else if (event.data.pluginMessage?.type === 'PROGRESS_PROCESSED_PAGES') { - setProcessedPages(event.data.pluginMessage.data as number); - } - }; - - const reload = () => { - setLoading(true); - parent.postMessage({ pluginMessage: { type: 'reload' } }, '*'); - }; - - const cancel = () => { - parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*'); - }; - - const exportPenpot = (data: FormValues) => { - setExporting(true); - - parent.postMessage( - { - pluginMessage: { - type: 'export', - data - } - }, - '*' - ); - }; - - useEffect(() => { - window.addEventListener('message', onMessage); - - parent.postMessage({ pluginMessage: { type: 'ready' } }, '*'); - - return () => { - window.removeEventListener('message', onMessage); - }; - }, []); - - return ( - - {children} - - ); + return {children}; }; -export { FigmaProvider, useFigma }; +export { FigmaProvider, useFigmaContext }; diff --git a/ui-src/context/useFigma.ts b/ui-src/context/useFigma.ts new file mode 100644 index 0000000..e4330a1 --- /dev/null +++ b/ui-src/context/useFigma.ts @@ -0,0 +1,150 @@ +import { useEffect, useState } from 'react'; + +import { FormValues } from '@ui/components/ExportForm'; +import { parse } from '@ui/parser'; +import { PenpotDocument } from '@ui/types'; + +export type UseFigmaHook = { + missingFonts: string[] | undefined; + needsReload: boolean; + loading: boolean; + exporting: boolean; + downloading: boolean; + currentNode: string | undefined; + totalPages: number | undefined; + processedPages: number | undefined; + reload: () => void; + cancel: () => void; + exportPenpot: (data: FormValues) => void; +}; + +type PluginMessage = + | PenpotDocumentMessage + | CustomFontsMessage + | ChangesDetectedMessage + | ProgressNodeMessage + | ProgressTotalPagesMessage + | ProgressProcessedPagesMessage; + +type PenpotDocumentMessage = { + type: 'PENPOT_DOCUMENT'; + data: PenpotDocument; +}; + +type CustomFontsMessage = { + type: 'CUSTOM_FONTS'; + data: string[]; +}; + +type ChangesDetectedMessage = { + type: 'CHANGES_DETECTED'; +}; + +type ProgressNodeMessage = { + type: 'PROGRESS_NODE'; + data: string; +}; + +type ProgressTotalPagesMessage = { + type: 'PROGRESS_TOTAL_PAGES'; + data: number; +}; + +type ProgressProcessedPagesMessage = { + type: 'PROGRESS_PROCESSED_PAGES'; + data: number; +}; + +export const useFigma = (): UseFigmaHook => { + const [missingFonts, setMissingFonts] = useState(); + const [needsReload, setNeedsReload] = useState(false); + const [loading, setLoading] = useState(true); + const [exporting, setExporting] = useState(false); + const [downloading, setDownloading] = useState(false); + const [currentNode, setCurrentNode] = useState(); + const [totalPages, setTotalPages] = useState(); + const [processedPages, setProcessedPages] = useState(); + + const postMessage = (type: string, data?: unknown) => { + parent.postMessage({ pluginMessage: { type, data } }, '*'); + }; + + const onMessage = (event: MessageEvent<{ pluginMessage?: PluginMessage }>) => { + if (!event.data.pluginMessage) return; + + const { pluginMessage } = event.data; + + switch (pluginMessage.type) { + case 'PENPOT_DOCUMENT': { + setDownloading(true); + + const file = parse(pluginMessage.data); + + file.export(); + break; + } + case 'CUSTOM_FONTS': { + setMissingFonts(pluginMessage.data); + setLoading(false); + setNeedsReload(false); + break; + } + case 'CHANGES_DETECTED': { + setNeedsReload(true); + break; + } + case 'PROGRESS_NODE': { + setCurrentNode(pluginMessage.data); + break; + } + case 'PROGRESS_TOTAL_PAGES': { + setTotalPages(pluginMessage.data); + setProcessedPages(0); + break; + } + case 'PROGRESS_PROCESSED_PAGES': { + setProcessedPages(pluginMessage.data); + break; + } + } + }; + + const reload = () => { + setLoading(true); + postMessage('reload'); + }; + + const cancel = () => { + postMessage('cancel'); + }; + + const exportPenpot = (data: FormValues) => { + setExporting(true); + + postMessage('export', data); + }; + + useEffect(() => { + window.addEventListener('message', onMessage); + + postMessage('ready'); + + return () => { + window.removeEventListener('message', onMessage); + }; + }, []); + + return { + missingFonts, + needsReload, + loading, + exporting, + downloading, + currentNode, + totalPages, + processedPages, + reload, + cancel, + exportPenpot + }; +};