Created
January 15, 2025 15:20
Redux store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { configureStore, AnyAction } from '@reduxjs/toolkit'; | |
import * as Sentry from '@sentry/electron/renderer'; | |
import { ThunkAction, ThunkDispatch } from 'redux-thunk'; | |
import { DEFAULT_PHP_VERSION } from '../../vendor/wp-now/src/constants'; | |
import { getIpcApi } from '../lib/get-ipc-api'; | |
// Types | |
type WPCliItem = { name: string }; | |
export interface ChatState { | |
// Site details | |
currentURL: string; | |
pluginList: string[]; | |
themeList: string[]; | |
numberOfSites: number; | |
phpVersion: string; | |
siteName: string; | |
isSiteLoadedDict: Record< string, boolean >; | |
// Theme details | |
themeName: string; | |
isBlockTheme: boolean; | |
// System details | |
os: string; | |
availableEditors: string[]; | |
wpVersion: string; | |
} | |
// Action Types | |
export const SET_SITE_INFO = 'chat/SET_SITE_INFO'; | |
export const SET_LISTS = 'chat/SET_LISTS'; | |
export const SET_SITE_LOADED_STATUS = 'chat/SET_SITE_LOADED_STATUS'; | |
export const UPDATE_THEME = 'chat/UPDATE_THEME'; | |
// Action Interfaces | |
interface SetSiteInfoAction { | |
type: typeof SET_SITE_INFO; | |
payload: { | |
currentURL: string; | |
phpVersion: string; | |
siteName: string; | |
isSiteLoadedDict: Record< string, boolean >; | |
}; | |
} | |
interface SetListsAction { | |
type: typeof SET_LISTS; | |
payload: { | |
plugins: string[]; | |
themes: string[]; | |
}; | |
} | |
interface SetSiteLoadedStatusAction { | |
type: typeof SET_SITE_LOADED_STATUS; | |
payload: { | |
siteId: string; | |
isLoaded: boolean; | |
}; | |
} | |
interface UpdateThemeAction { | |
type: typeof UPDATE_THEME; | |
payload: { | |
name: string; | |
isBlockTheme: boolean; | |
}; | |
} | |
type ChatActionTypes = | |
| SetSiteInfoAction | |
| SetListsAction | |
| SetSiteLoadedStatusAction | |
| UpdateThemeAction; | |
// Action Creators | |
export const setSiteInfo = ( | |
currentURL: string, | |
phpVersion: string, | |
siteName: string, | |
isSiteLoadedDict: Record< string, boolean > | |
): SetSiteInfoAction => ( { | |
type: SET_SITE_INFO, | |
payload: { currentURL, phpVersion, siteName, isSiteLoadedDict }, | |
} ); | |
export const setLists = ( plugins: string[], themes: string[] ): SetListsAction => ( { | |
type: SET_LISTS, | |
payload: { plugins, themes }, | |
} ); | |
export const setSiteLoadedStatus = ( | |
siteId: string, | |
isLoaded: boolean | |
): SetSiteLoadedStatusAction => ( { | |
type: SET_SITE_LOADED_STATUS, | |
payload: { siteId, isLoaded }, | |
} ); | |
export const updateTheme = ( name: string, isBlockTheme: boolean ): UpdateThemeAction => ( { | |
type: UPDATE_THEME, | |
payload: { name, isBlockTheme }, | |
} ); | |
// Async Action Creators | |
export const fetchPluginList = ( | |
siteId: string | |
): ThunkAction< Promise< string[] >, ChatState, unknown, AnyAction > => { | |
return async () => { | |
const { stdout, stderr } = await getIpcApi().executeWPCLiInline( { | |
siteId, | |
args: 'plugin list --format=json --status=active', | |
skipPluginsAndThemes: true, | |
} ); | |
if ( stderr ) { | |
return []; | |
} | |
try { | |
const data = JSON.parse( stdout ); | |
return data?.map( ( item: WPCliItem ) => item.name ) || []; | |
} catch ( error ) { | |
Sentry.captureException( error, { extra: { stdout } } ); | |
return []; | |
} | |
}; | |
}; | |
export const fetchThemeList = ( | |
siteId: string | |
): ThunkAction< Promise< string[] >, ChatState, unknown, AnyAction > => { | |
return async () => { | |
const { stdout, stderr } = await getIpcApi().executeWPCLiInline( { | |
siteId, | |
args: 'theme list --format=json', | |
skipPluginsAndThemes: true, | |
} ); | |
if ( stderr ) { | |
return []; | |
} | |
try { | |
const data = JSON.parse( stdout ); | |
return data?.map( ( item: WPCliItem ) => item.name ) || []; | |
} catch ( error ) { | |
Sentry.captureException( error, { extra: { stdout } } ); | |
return []; | |
} | |
}; | |
}; | |
export const updateFromSite = ( | |
site: SiteDetails | |
): ThunkAction< Promise< void >, ChatState, unknown, AnyAction > => { | |
return async ( dispatch: ThunkDispatch< ChatState, unknown, AnyAction > ) => { | |
dispatch( | |
setSiteInfo( | |
`http://localhost:${ site.port }`, | |
site.phpVersion ?? DEFAULT_PHP_VERSION, | |
site.name, | |
{ [ site.id ]: true } | |
) | |
); | |
try { | |
const [ plugins, themes ] = await Promise.all( [ | |
dispatch( fetchPluginList( site.id ) ), | |
dispatch( fetchThemeList( site.id ) ), | |
] ); | |
dispatch( setLists( plugins, themes ) ); | |
} catch ( error ) { | |
dispatch( setSiteLoadedStatus( site.id, false ) ); | |
} | |
}; | |
}; | |
// Initial State | |
const initialState: ChatState = { | |
currentURL: '', | |
pluginList: [], | |
themeList: [], | |
numberOfSites: 0, | |
themeName: '', | |
wpVersion: '', | |
phpVersion: DEFAULT_PHP_VERSION, | |
isBlockTheme: false, | |
os: window.appGlobals?.platform || '', | |
availableEditors: [], | |
siteName: '', | |
isSiteLoadedDict: {}, | |
}; | |
// Reducer | |
function chatReducer( state = initialState, action: ChatActionTypes ): ChatState { | |
switch ( action.type ) { | |
case SET_SITE_INFO: | |
return { | |
...state, | |
currentURL: action.payload.currentURL, | |
phpVersion: action.payload.phpVersion, | |
siteName: action.payload.siteName, | |
isSiteLoadedDict: { ...state.isSiteLoadedDict, ...action.payload.isSiteLoadedDict }, | |
}; | |
case SET_LISTS: | |
return { | |
...state, | |
pluginList: action.payload.plugins, | |
themeList: action.payload.themes, | |
}; | |
case SET_SITE_LOADED_STATUS: | |
return { | |
...state, | |
isSiteLoadedDict: { | |
...state.isSiteLoadedDict, | |
[ action.payload.siteId ]: action.payload.isLoaded, | |
}, | |
}; | |
case UPDATE_THEME: | |
return { | |
...state, | |
themeName: action.payload.name, | |
isBlockTheme: action.payload.isBlockTheme, | |
}; | |
default: | |
return state; | |
} | |
} | |
// Store | |
export const chatStore = configureStore( { | |
reducer: chatReducer, | |
} ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment