Frontend audit: Bug fixes and refinements (#2112)

* (fix:attachements) sep id for redux ops

* (fix:ui) popups, toast, share modal

* (feat:agentsPreview) stable preview, ui fixes

* (fix:ui) light theme icon, sleek scroll

* (chore:i18n) missin keys

* (chore:i18n) missing keys

* (feat:preferrenceSlice) autoclear invalid source from storage

* (fix:general) delete all conv close btn

* (fix:tts) play one at a time

* (fix:tts) gracefully unmount

* (feat:tts) audio LRU cache

* (feat:tts) pointer on hovered area

* (feat:tts) clean text for speach

---------

Co-authored-by: GH Action - Upstream Sync <action@github.com>
This commit is contained in:
Manish Madan
2025-10-29 05:17:26 +05:30
committed by GitHub
parent 94f70e6de5
commit 6a4cb617f9
40 changed files with 1805 additions and 490 deletions

View File

@@ -54,7 +54,7 @@ function AddPrompt({
className="border-silver dark:border-silver/40 h-56 w-full resize-none rounded-lg border-2 px-3 py-2 outline-hidden dark:bg-transparent dark:text-white"
value={newPromptContent}
onChange={(e) => setNewPromptContent(e.target.value)}
aria-label="Prompt Text"
aria-label={t('prompts.textAriaLabel')}
></textarea>
</div>
<div className="mt-6 flex flex-row-reverse">
@@ -126,7 +126,7 @@ function EditPrompt({
className="border-silver dark:border-silver/40 h-56 w-full resize-none rounded-lg border-2 px-3 py-2 outline-hidden dark:bg-transparent dark:text-white"
value={editPromptContent}
onChange={(e) => setEditPromptContent(e.target.value)}
aria-label="Prompt Text"
aria-label={t('prompts.textAriaLabel')}
></textarea>
</div>
<div className="mt-6 flex flex-row-reverse gap-4">

View File

@@ -90,9 +90,27 @@ export function getLocalApiKey(): string | null {
return key;
}
export function getLocalRecentDocs(): Doc[] | null {
const docs = localStorage.getItem('DocsGPTRecentDocs');
return docs ? (JSON.parse(docs) as Doc[]) : null;
export function getLocalRecentDocs(sourceDocs?: Doc[] | null): Doc[] | null {
const docsString = localStorage.getItem('DocsGPTRecentDocs');
const selectedDocs = docsString ? (JSON.parse(docsString) as Doc[]) : null;
if (!sourceDocs || !selectedDocs || selectedDocs.length === 0) {
return selectedDocs;
}
const isDocAvailable = (selected: Doc) => {
return sourceDocs.some((source) => {
if (source.id && selected.id) {
return source.id === selected.id;
}
return source.name === selected.name && source.date === selected.date;
});
};
const validDocs = selectedDocs.filter(isDocAvailable);
setLocalRecentDocs(validDocs.length > 0 ? validDocs : null);
return validDocs.length > 0 ? validDocs : null;
}
export function getLocalPrompt(): string | null {

View File

@@ -8,7 +8,11 @@ import {
import { Agent } from '../agents/types';
import { ActiveState, Doc } from '../models/misc';
import { RootState } from '../store';
import { setLocalApiKey, setLocalRecentDocs } from './preferenceApi';
import {
setLocalApiKey,
setLocalRecentDocs,
getLocalRecentDocs,
} from './preferenceApi';
export interface Preference {
apiKey: string;
@@ -178,6 +182,22 @@ prefListenerMiddleware.startListening({
},
});
prefListenerMiddleware.startListening({
matcher: isAnyOf(setSourceDocs),
effect: (_action, listenerApi) => {
const state = listenerApi.getState() as RootState;
const sourceDocs = state.preference.sourceDocs;
if (sourceDocs && sourceDocs.length > 0) {
const validatedDocs = getLocalRecentDocs(sourceDocs);
if (validatedDocs !== null) {
listenerApi.dispatch(setSelectedDocs(validatedDocs));
} else {
listenerApi.dispatch(setSelectedDocs([]));
}
}
},
});
export const selectApiKey = (state: RootState) => state.preference.apiKey;
export const selectApiKeyStatus = (state: RootState) =>
!!state.preference.apiKey;