PluginProbe
Extendify / 3.1.5
Extendify v3.1.5
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / src / Launch / LaunchPage.jsx

LaunchPage.jsx in Extendify 3.1.5, at src/Launch/LaunchPage.jsx

159 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { updateOption } from '@launch/api/WPApi';
2 import { RestartLaunchModal } from '@launch/components/RestartLaunchModal';
3 import { RetryNotice } from '@launch/components/RetryNotice';
4 import { useTelemetry } from '@launch/hooks/useTelemetry';
5 import { CreatingSite } from '@launch/pages/CreatingSite';
6 import { NeedsTheme } from '@launch/pages/NeedsTheme';
7 import { useGlobalStore } from '@launch/state/Global';
8 import { usePagesStore } from '@launch/state/Pages';
9 import { safeParseJson } from '@shared/lib/parsing';
10 import { registerCoreBlocks } from '@wordpress/block-library';
11 import { getBlockTypes } from '@wordpress/blocks';
12 import { useDispatch, useSelect } from '@wordpress/data';
13 import { useEffect, useRef, useState } from '@wordpress/element';
14 import { __ } from '@wordpress/i18n';
15 import { SWRConfig, useSWRConfig } from 'swr';
16
17 export const LaunchPage = () => {
18 const { updateSettings } = useDispatch('core/block-editor');
19 const [retrying, setRetrying] = useState(false);
20 const { component: CurrentPage, state } = usePagesStore((state) =>
21 state.getCurrentPageData(),
22 );
23 const { fetcher, fetchData } = usePagesStore((state) =>
24 state.getNextPageData(),
25 );
26 const { setPage } = usePagesStore();
27 const { mutate } = useSWRConfig();
28 const { generating } = useGlobalStore();
29 const [show, setShow] = useState(false);
30 const [needsTheme, setNeedsTheme] = useState(false);
31 const theme = useSelect((select) => select('core').getCurrentTheme());
32 useTelemetry();
33 const once = useRef(false);
34
35 const page = () => {
36 if (needsTheme) return <NeedsTheme />;
37 if (generating) return <CreatingSite />;
38 if (!CurrentPage) return null;
39 return (
40 <>
41 <RestartLaunchModal setPage={setPage} />
42 <CurrentPage />
43 </>
44 );
45 };
46
47 useEffect(() => {
48 if (once.current) return;
49 once.current = true;
50 // on page load, if we are on a page without nav, go to the first page
51 if (state.getState().useNav) return;
52 setPage(0);
53 }, [state, setPage]);
54
55 useEffect(() => {
56 // translators: Launch is a noun.
57 document.title = __('Launch - AI-Powered Web Creation', 'extendify-local');
58 }, []);
59
60 useEffect(() => {
61 // Add editor styles to use for live previews
62 let editorStyles = window.extOnbData.editorStyles;
63 const settings = safeParseJson(editorStyles);
64
65 // Fix asset URLs when the site is accessed via a different domain than
66 // configured (e.g., temporary/staging URLs in hosted environments).
67 // This prevents CORS errors with fonts in BlockPreview iframes.
68 const baseURL = settings?.styles?.find((s) => s.baseURL)?.baseURL;
69 if (baseURL) {
70 try {
71 const configuredHost = new URL(baseURL).host;
72 const currentHost = window.location.host;
73 if (configuredHost !== currentHost) {
74 editorStyles = editorStyles.replaceAll(configuredHost, currentHost);
75 updateSettings(safeParseJson(editorStyles));
76 return;
77 }
78 } catch (_e) {
79 // Invalid URL, skip rewriting
80 }
81 }
82
83 updateSettings(settings);
84 }, [updateSettings]);
85
86 useEffect(() => {
87 if (getBlockTypes().length !== 0) return;
88 registerCoreBlocks();
89 }, []);
90
91 useEffect(() => {
92 // Check that the textdomain came back and that it's extendable
93 if (!theme?.textdomain) return;
94 if (theme?.textdomain === 'extendable') return;
95 setNeedsTheme(true);
96 }, [theme]);
97
98 useEffect(() => {
99 setShow(true);
100 updateOption('extendify_launch_loaded', new Date().toISOString());
101 }, []);
102
103 useEffect(() => {
104 const fetchers = [].concat(fetcher);
105 const fetchDataArrays = [].concat(fetchData);
106 if (fetchers.length) {
107 fetchers.forEach((fetcher, i) => {
108 try {
109 const data =
110 typeof fetchDataArrays?.[i] === 'function'
111 ? fetchDataArrays[i]()
112 : fetchDataArrays?.[i];
113 mutate(data, (last) => last || fetcher(data), { revalidate: false });
114 } catch (_e) {
115 //
116 }
117 });
118 }
119 }, [fetcher, mutate, fetchData]);
120
121 if (!show) return null;
122
123 return (
124 <SWRConfig
125 value={{
126 errorRetryInterval: 1000,
127 onErrorRetry: (error, key, _config, revalidate, { retryCount }) => {
128 if (error?.data?.status === 403) {
129 // if they are logged out, we can't recover
130 window.location.reload();
131 return;
132 }
133 if (retrying) return;
134
135 // TODO: Add back when we have something to show here
136 // if (retryCount >= 5) {
137 // console.error('Encountered unrecoverable error', error)
138 // throw new Error(error?.message ?? 'Unknown error')
139 // }
140 console.error(key, error);
141 setRetrying(true);
142 setTimeout(() => {
143 setRetrying(false);
144 revalidate({ retryCount });
145 }, 5000);
146 },
147 }}
148 >
149 <div
150 style={{ zIndex: 99999 + 1 }} // 1 more than the library
151 className="fixed inset-0 h-screen w-screen overflow-y-auto bg-white md:overflow-hidden"
152 >
153 {page()}
154 </div>
155 <RetryNotice show={retrying} />
156 </SWRConfig>
157 );
158 };
159