0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 05:33:02 -05:00

Refactor context (#139)

* Refactor context

* fix

* fix
This commit is contained in:
Jordi Sala Morales 2024-06-04 18:02:59 +02:00 committed by GitHub
parent df30dfd376
commit 4b711b3526
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 166 additions and 115 deletions

View file

@ -2,14 +2,14 @@ import { Button } from '@create-figma-plugin/ui';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { Stack } from '@ui/components/Stack'; import { Stack } from '@ui/components/Stack';
import { useFigma } from '@ui/context'; import { useFigmaContext } from '@ui/context';
import { MissingFontsSection } from './MissingFontsSection'; import { MissingFontsSection } from './MissingFontsSection';
export type FormValues = Record<string, string>; export type FormValues = Record<string, string>;
export const ExportForm = () => { export const ExportForm = () => {
const { cancel, exportPenpot } = useFigma(); const { cancel, exportPenpot } = useFigmaContext();
const methods = useForm<FormValues>(); const methods = useForm<FormValues>();
return ( return (

View file

@ -1,11 +1,11 @@
import { LoadingIndicator } from '@create-figma-plugin/ui'; import { LoadingIndicator } from '@create-figma-plugin/ui';
import { useFigma } from '@ui/context'; import { useFigmaContext } from '@ui/context';
import { Stack } from './Stack'; import { Stack } from './Stack';
export const ExporterProgress = () => { export const ExporterProgress = () => {
const { currentNode, totalPages, processedPages, downloading } = useFigma(); const { currentNode, totalPages, processedPages, downloading } = useFigmaContext();
const truncateText = (text: string, maxChars: number) => { const truncateText = (text: string, maxChars: number) => {
if (text.length <= maxChars) { if (text.length <= maxChars) {

View file

@ -1,12 +1,12 @@
import { Banner, IconInfo32, Link, Textbox } from '@create-figma-plugin/ui'; import { Banner, IconInfo32, Link, Textbox } from '@create-figma-plugin/ui';
import { Controller, useFormContext } from 'react-hook-form'; import { Controller, useFormContext } from 'react-hook-form';
import { useFigma } from '@ui/context'; import { useFigmaContext } from '@ui/context';
import { Stack } from './Stack'; import { Stack } from './Stack';
export const MissingFontsSection = () => { export const MissingFontsSection = () => {
const { missingFonts } = useFigma(); const { missingFonts } = useFigmaContext();
if (!missingFonts || !missingFonts.length) return null; if (!missingFonts || !missingFonts.length) return null;

View file

@ -1,13 +1,13 @@
import { LoadingIndicator } from '@create-figma-plugin/ui'; import { LoadingIndicator } from '@create-figma-plugin/ui';
import { useFigma } from '@ui/context'; import { useFigmaContext } from '@ui/context';
import { ExportForm } from './ExportForm'; import { ExportForm } from './ExportForm';
import { ExporterProgress } from './ExporterProgress'; import { ExporterProgress } from './ExporterProgress';
import { PluginReload } from './PluginReload'; import { PluginReload } from './PluginReload';
export const PenpotExporter = () => { export const PenpotExporter = () => {
const { loading, needsReload, exporting } = useFigma(); const { loading, needsReload, exporting } = useFigmaContext();
if (loading) return <LoadingIndicator />; if (loading) return <LoadingIndicator />;

View file

@ -1,10 +1,10 @@
import { Banner, Button, IconInfo32 } from '@create-figma-plugin/ui'; import { Banner, Button, IconInfo32 } from '@create-figma-plugin/ui';
import { Stack } from '@ui/components/Stack'; import { Stack } from '@ui/components/Stack';
import { useFigma } from '@ui/context'; import { useFigmaContext } from '@ui/context';
export const PluginReload = () => { export const PluginReload = () => {
const { reload, cancel } = useFigma(); const { reload, cancel } = useFigmaContext();
return ( return (
<Stack space="small"> <Stack space="small">

View file

@ -1,113 +1,14 @@
import { JSX, PropsWithChildren, useEffect, useState } from 'react'; import { JSX, PropsWithChildren } from 'react';
import { FormValues } from '@ui/components/ExportForm';
import { parse } from '@ui/parser';
import { PenpotDocument } from '@ui/types';
import { createGenericContext } from './createGenericContext'; import { createGenericContext } from './createGenericContext';
import { UseFigmaHook, useFigma } from './useFigma';
type Context = { const [useFigmaContext, StateContextProvider] = createGenericContext<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;
};
const [useFigma, StateContextProvider] = createGenericContext<Context>();
const FigmaProvider = ({ children }: PropsWithChildren): JSX.Element => { const FigmaProvider = ({ children }: PropsWithChildren): JSX.Element => {
const [missingFonts, setMissingFonts] = useState<string[]>(); const hook = useFigma();
const [needsReload, setNeedsReload] = useState(false);
const [loading, setLoading] = useState(true);
const [exporting, setExporting] = useState(false);
const [downloading, setDownloading] = useState(false);
const [currentNode, setCurrentNode] = useState<string | undefined>();
const [totalPages, setTotalPages] = useState<number | undefined>();
const [processedPages, setProcessedPages] = useState<number | undefined>();
const onMessage = (event: MessageEvent<{ pluginMessage: { type: string; data: unknown } }>) => { return <StateContextProvider value={hook}>{children}</StateContextProvider>;
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 (
<StateContextProvider
value={{
missingFonts,
needsReload,
loading,
exporting,
downloading,
currentNode,
totalPages,
processedPages,
reload,
cancel,
exportPenpot
}}
>
{children}
</StateContextProvider>
);
}; };
export { FigmaProvider, useFigma }; export { FigmaProvider, useFigmaContext };

150
ui-src/context/useFigma.ts Normal file
View file

@ -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<string[]>();
const [needsReload, setNeedsReload] = useState(false);
const [loading, setLoading] = useState(true);
const [exporting, setExporting] = useState(false);
const [downloading, setDownloading] = useState(false);
const [currentNode, setCurrentNode] = useState<string | undefined>();
const [totalPages, setTotalPages] = useState<number | undefined>();
const [processedPages, setProcessedPages] = useState<number | undefined>();
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
};
};