diff --git a/webapp/src/bots.tsx b/webapp/src/bots.tsx index 29505602..82ca0e6f 100644 --- a/webapp/src/bots.tsx +++ b/webapp/src/bots.tsx @@ -1,11 +1,14 @@ import {useState, useEffect} from 'react'; -import {useSelector} from 'react-redux'; +import {useDispatch, useSelector} from 'react-redux'; import {GlobalState} from '@mattermost/types/store'; import {getAIBots} from '@/client'; +import manifest from './manifest'; +import {BotsHandler} from './redux'; + export interface LLMBot { id: string; displayName: string; @@ -17,9 +20,10 @@ export interface LLMBot { const defaultBotLocalStorageKey = 'defaultBot'; export const useBotlist = () => { - const [bots, setBots] = useState(null); - const [activeBot, setActiveBotState] = useState(null); + const bots = useSelector((state: any) => state['plugins-' + manifest.id].bots); + const [activeBot, setActiveBot] = useState(null); const currentUserId = useSelector((state) => state.entities.users.currentUserId); + const dispatch = useDispatch(); // Load bots useEffect(() => { @@ -29,26 +33,27 @@ export const useBotlist = () => { return; } - // Set default bot to the one in local storage otherwise default to the first bot (which should be the server default) - let newActiveBot = fetchedBots[0]; - if (fetchedBots.length > 1) { - const defaultBotName = localStorage.getItem(defaultBotLocalStorageKey); - const defaultBot = fetchedBots.find((bot: LLMBot) => bot.username === defaultBotName); - if (defaultBot) { - newActiveBot = defaultBot; - } - } - - setBots(fetchedBots); - setActiveBotState(newActiveBot); + dispatch({ + type: BotsHandler, + bots: fetchedBots, + }); }; - fetchBots(); - }, [currentUserId]); + if (!bots) { + fetchBots(); + } + }, [currentUserId, bots, dispatch]); - const setActiveBot = (bot: LLMBot) => { - setActiveBotState(bot); - localStorage.setItem(defaultBotLocalStorageKey, bot.username); - }; + useEffect(() => { + const defaultActiveBotName = localStorage.getItem(defaultBotLocalStorageKey); + setActiveBot(bots?.find((bot: LLMBot) => bot.username === defaultActiveBotName) || bots?.[0] || null); + }, [bots]); + + useEffect(() => { + if (!activeBot) { + return; + } + localStorage.setItem(defaultBotLocalStorageKey, activeBot.username); + }, [activeBot]); return {bots, activeBot, setActiveBot}; }; diff --git a/webapp/src/index.tsx b/webapp/src/index.tsx index 10f3576c..1756c3e4 100644 --- a/webapp/src/index.tsx +++ b/webapp/src/index.tsx @@ -20,7 +20,7 @@ import {doReaction, doSummarize, getAIDirectChannel} from './client'; import {setOpenRHSAction} from './redux_actions'; import {BotUsername} from './constants'; import PostEventListener from './websocket'; -import {setupRedux} from './redux'; +import {BotsHandler, setupRedux} from './redux'; import UnreadsSumarize from './components/unreads_summarize'; import {PostbackPost} from './components/postback_post'; @@ -84,23 +84,6 @@ export default class Plugin { if ((window as any).Components.CreatePost) { rhs = registry.registerRightHandSidebarComponent(RHS, RHSTitle); setOpenRHSAction(rhs.showRHSPlugin); - - registry.registerReducer((state = {}, action: any) => { - switch (action.type) { - case 'SET_AI_BOT_CHANNEL': - return { - ...state, - botChannelId: action.botChannelId, - }; - case 'SELECT_AI_POST': - return { - ...state, - selectedPostId: action.postId, - }; - default: - return state; - } - }); } let currentUserId = store.getState().entities.users.currentUserId; @@ -136,6 +119,13 @@ export default class Plugin { ; }; + registry.registerWebSocketEventHandler('config_changed', (message: any) => { + store.dispatch({ + type: BotsHandler, + bots: null, + } as any); + }); + registry.registerPostTypeComponent('custom_llmbot', LLMBotPostWithWebsockets); registry.registerPostTypeComponent('custom_llm_postback', PostbackPost); if (registry.registerPostActionComponent) { diff --git a/webapp/src/redux.tsx b/webapp/src/redux.tsx index 40f18ed0..c061c0d0 100644 --- a/webapp/src/redux.tsx +++ b/webapp/src/redux.tsx @@ -2,17 +2,22 @@ import {combineReducers, Store, Action} from 'redux'; import {GlobalState} from '@mattermost/types/lib/store'; import {makeCallsPostButtonClickedHandler} from './calls_button'; +import manifest from './manifest'; type WebappStore = Store>> const CallsClickHandler = 'calls_post_button_clicked_handler'; +export const BotsHandler = manifest.id + '_bots'; export async function setupRedux(registry: any, store: WebappStore) { const reducer = combineReducers({ callsPostButtonClickedTranscription, + bots, + botChannelId, + selectedPostId, }); - registry.registerReducer(reducer); + store.dispatch({ type: CallsClickHandler as any, handler: makeCallsPostButtonClickedHandler(store.dispatch), @@ -46,3 +51,30 @@ function callsPostButtonClickedTranscription(state = false, action: any) { return state; } } + +function bots(state = null, action: any) { + switch (action.type) { + case BotsHandler: + return action.bots; + default: + return state; + } +} + +function botChannelId(state = '', action: any) { + switch (action.type) { + case 'SET_AI_BOT_CHANNEL': + return action.botChannelId; + default: + return state; + } +} + +function selectedPostId(state = '', action: any) { + switch (action.type) { + case 'SELECT_AI_POST': + return action.postId; + default: + return state; + } +}