Fixes: re-blink in converstaion, (refactor) prompts and validate LocalStorage prompts (#2181)

* chore(dependabot): add react-widget npm dependency updates

* refactor(prompts): init on load, mv to pref slice

* (refactor): searchable dropdowns are separate

* (fix/ui) prompts adjust

* feat(changelog): dancing stars

* (fix)conversation: re-blink bubble past stream

* (fix)endless GET sources, esling err

---------

Co-authored-by: GH Action - Upstream Sync <action@github.com>
This commit is contained in:
Manish Madan
2025-12-11 03:23:40 +05:30
committed by GitHub
parent 4adffe762a
commit 09e7c1b97f
14 changed files with 613 additions and 129 deletions

View File

@@ -2,17 +2,17 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import userService from '../api/services/userService';
import Dropdown from '../components/Dropdown';
import { useDarkTheme } from '../hooks';
import {
selectChunks,
selectPrompt,
selectToken,
selectPrompts,
selectTokenLimit,
setChunks,
setModalStateDeleteConv,
setPrompt,
setPrompts,
setTokenLimit,
} from '../preferences/preferenceSlice';
import Prompts from './Prompts';
@@ -22,7 +22,6 @@ export default function General() {
t,
i18n: { changeLanguage },
} = useTranslation();
const token = useSelector(selectToken);
const themes = [
{ value: 'Light', label: t('settings.general.light') },
{ value: 'Dark', label: t('settings.general.dark') },
@@ -46,9 +45,7 @@ export default function General() {
[4000, t('settings.general.high')],
[1e9, t('settings.general.unlimited')],
]);
const [prompts, setPrompts] = React.useState<
{ name: string; id: string; type: string }[]
>([]);
const prompts = useSelector(selectPrompts);
const selectedChunks = useSelector(selectChunks);
const selectedTokenLimit = useSelector(selectTokenLimit);
const [isDarkTheme, toggleTheme] = useDarkTheme();
@@ -64,22 +61,6 @@ export default function General() {
);
const selectedPrompt = useSelector(selectPrompt);
React.useEffect(() => {
const handleFetchPrompts = async () => {
try {
const response = await userService.getPrompts(token);
if (!response.ok) {
throw new Error('Failed to fetch prompts');
}
const promptsData = await response.json();
setPrompts(promptsData);
} catch (error) {
console.error(error);
}
};
handleFetchPrompts();
}, []);
React.useEffect(() => {
localStorage.setItem('docsgpt-locale', selectedLanguage?.value as string);
changeLanguage(selectedLanguage?.value);
@@ -169,7 +150,7 @@ export default function General() {
onSelectPrompt={(name, id, type) =>
dispatch(setPrompt({ name: name, id: id, type: type }))
}
setPrompts={setPrompts}
setPrompts={(newPrompts) => dispatch(setPrompts(newPrompts))}
dropdownProps={{ size: 'w-56', rounded: '3xl', border: 'border' }}
/>
</div>

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import userService from '../api/services/userService';
import Dropdown from '../components/Dropdown';
import SearchableDropdown from '../components/SearchableDropdown';
import { DropdownProps } from '../components/types/Dropdown.types';
import ConfirmationModal from '../modals/ConfirmationModal';
import { ActiveState, PromptProps } from '../models/misc';
@@ -103,7 +103,12 @@ export default function Prompts({
if (!response.ok) {
throw new Error('Failed to delete prompt');
}
if (prompts.length > 0) {
// Only change selection if we're deleting the currently selected prompt
if (
prompts.length > 0 &&
selectedPrompt &&
selectedPrompt.id === promptToDelete.id
) {
const firstPrompt = prompts.find((p) => p.id !== promptToDelete.id);
if (firstPrompt) {
onSelectPrompt(
@@ -182,7 +187,7 @@ export default function Prompts({
{title ? title : t('settings.general.prompt')}
</p>
<div className="flex flex-row flex-wrap items-baseline justify-start gap-6">
<Dropdown
<SearchableDropdown
options={prompts.map((prompt: any) =>
typeof prompt === 'string'
? { name: prompt, id: prompt, type: '' }