PluginProbe
Extendify / 3.1.0
Extendify v3.1.0
3.2.1 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 All 127 releases
extendify / src / AutoLaunch / state / launch-data.js

launch-data.js in Extendify 3.1.0, at src/AutoLaunch/state/launch-data.js

185 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 getDesignBuildShape,
3 getHomeShape,
4 getImagesShape,
5 getLaunchDecisionsShape,
6 getLogoShape,
7 getPagesShape,
8 getPluginsShape,
9 getProfileShape,
10 getStringsShape,
11 getStyleShape,
12 } from '@auto-launch/fetchers/shape';
13 import { clearSiteImages } from '@auto-launch/functions/wp';
14 import { __ } from '@wordpress/i18n';
15 import { create } from 'zustand';
16 import { devtools, persist } from 'zustand/middleware';
17 import { overrideWithUrlParams, urlParams, urlParamsShape } from './url-params';
18
19 const shapeToKeyValue = (shape) => {
20 return Object.fromEntries(
21 Object.keys(shape.shape).map((key) => [key, undefined]),
22 );
23 };
24
25 const initialState = {
26 go: false,
27 // translators: this is for a action log UI. Keep it short
28 statusMessages: [__('Booting things up', 'extendify-local')],
29 errorMessage: null,
30 errorCount: 0,
31 title: null,
32 description: null,
33 descriptionBackup: undefined,
34 descriptionRaw: null,
35 urlParams: {},
36 siteProfile: {
37 ...shapeToKeyValue(getProfileShape),
38 },
39 launchDecisions: {
40 ...shapeToKeyValue(getLaunchDecisionsShape),
41 },
42 ...shapeToKeyValue(getLogoShape),
43 ...shapeToKeyValue(getPluginsShape),
44 ...shapeToKeyValue(getStyleShape),
45 ...shapeToKeyValue(getStringsShape),
46 ...shapeToKeyValue(getImagesShape),
47 ...shapeToKeyValue(getHomeShape),
48 ...shapeToKeyValue(getPagesShape),
49 ...shapeToKeyValue(getDesignBuildShape),
50 designBuild: undefined,
51 attempt: 1,
52 };
53
54 const state = (set, get) => ({
55 ...initialState,
56 urlParams: {
57 ...initialState.urlParams,
58 ...urlParams,
59 },
60 title: undefined,
61 description: undefined,
62 descriptionBackup: undefined,
63 descriptionRaw: undefined,
64 pulse: false,
65 setPulse: (value) => set({ pulse: value }),
66 setData: (key, value) => {
67 if (!isValidKey(key)) return;
68 if (get()[key] === value) return; // avoid unnecessary updates
69 set({ [key]: value });
70 },
71 addStatusMessage: (message) => {
72 const currentMessages = get().statusMessages;
73 // remove any previous duplicates
74 const prev = currentMessages.filter((msg) => msg !== message);
75 set({ statusMessages: [...prev, message] });
76 },
77 setErrorMessage: (message) => {
78 set((state) => ({
79 errorMessage: message,
80 errorCount: state.errorCount + 1,
81 }));
82 },
83 needToStall: () => get().errorCount > 6,
84 resetErrorCount: () => {
85 set({ errorCount: 0 });
86 },
87 reset: ({ exclude }) => {
88 const newState = { ...initialState, attempt: get().attempt + 1 };
89 if (exclude && Array.isArray(exclude)) {
90 exclude.forEach((key) => {
91 if (!isValidKey(key)) return;
92 newState[key] = get()[key];
93 });
94 }
95 clearSiteImages().catch(() => null);
96 set(newState);
97 },
98 });
99
100 // Checks that a key being set is actually something we expect
101 const isValidKey = (key) => Object.keys(initialState).includes(key);
102
103 const keySchemas = {
104 urlParams: urlParamsShape,
105 siteProfile: getProfileShape,
106 launchDecisions: getLaunchDecisionsShape,
107 ...Object.fromEntries(
108 [
109 getLogoShape,
110 getPluginsShape,
111 getStyleShape,
112 getStringsShape,
113 getImagesShape,
114 getHomeShape,
115 getPagesShape,
116 getDesignBuildShape,
117 ].flatMap((s) => Object.entries(s.shape)),
118 ),
119 };
120
121 export const useLaunchDataStore = create(
122 persist(devtools(state, { name: 'Extendify Launch Data' }), {
123 name: `extendify-launch-data-${window.extSharedData.siteId}`,
124 merge: (p, current) => {
125 // Make sure the persisted state is valid and not corrupted.
126 const persisted = p && typeof p === 'object' ? p : {};
127
128 // This gives us some recovery on page reload
129 const validated = Object.fromEntries(
130 Object.entries(persisted)
131 .filter(([key]) => key in keySchemas)
132 .map(([key, value]) => {
133 const result = keySchemas[key].safeParse(value);
134 return [key, result.success ? result.data : undefined];
135 }),
136 );
137 // Merge in the url params
138 const { title, description, go, ...urlParamsMapped } =
139 overrideWithUrlParams(urlParams);
140
141 return {
142 ...current,
143 ...persisted,
144 ...validated,
145 // If there's a URL param here it should override these values
146 title: title || persisted.title,
147 description: description || persisted.description,
148 descriptionRaw: description || persisted.descriptionRaw,
149 descriptionBackup: persisted.descriptionBackup || description || title,
150 go: go || persisted.go,
151 urlParams: {
152 title,
153 description,
154 go,
155 ...urlParamsMapped,
156 },
157 };
158 },
159 onRehydrateStorage: () => (state) => {
160 if (!state) return;
161 queueMicrotask(() => {
162 useLaunchDataStore.setState(state);
163 });
164 },
165 partialize: (state) => {
166 const {
167 statusMessages,
168 errorMessage,
169 errorCount,
170 pulse,
171 description,
172 descriptionRaw,
173 title,
174 ...rest
175 } = state;
176 return Object.fromEntries(
177 Object.entries(rest).filter(([, v]) =>
178 Array.isArray(v) ? v.length > 0 : Boolean(v),
179 ),
180 );
181 },
182 }),
183 state,
184 );
185