Add settings toggle for previous-conversation context (#66).
Unit Tests / test (pull_request) Successful in 11s
Unit Tests / test (pull_request) Successful in 11s
Wire Account Preferences to use_conversation_context via preferences API, with tooltip copy plus loading and error handling on update.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import InfoOutlined from '@mui/icons-material/InfoOutlined';
|
||||
import {
|
||||
useMaterialUIController,
|
||||
setDarkMode,
|
||||
@@ -48,6 +50,16 @@ const SettingLabel = styled.span`
|
||||
font-size: 1.1rem;
|
||||
color: ${({ theme }) => theme.colors.text};
|
||||
font-weight: 500;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
`;
|
||||
|
||||
const InfoIcon = styled(InfoOutlined)`
|
||||
font-size: 1rem !important;
|
||||
opacity: 0.7;
|
||||
cursor: help;
|
||||
vertical-align: middle;
|
||||
`;
|
||||
|
||||
const ToggleSwitch = styled.label`
|
||||
@@ -93,6 +105,11 @@ const Checkbox = styled.input`
|
||||
&:checked + ${Slider}:before {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
&:disabled + ${Slider} {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`;
|
||||
|
||||
const ColorPickerContainer = styled.div`
|
||||
@@ -115,6 +132,23 @@ const ColorButton = styled.button<{ color: string; isSelected: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const ErrorText = styled.p`
|
||||
color: #ff6b6b;
|
||||
margin: 0.75rem 0 0 0;
|
||||
font-size: 0.95rem;
|
||||
`;
|
||||
|
||||
const CONTEXT_TOOLTIP =
|
||||
'This will use previous conversations to better customize the experience.';
|
||||
|
||||
function prefsErrorMessage(error: unknown, fallback: string): string {
|
||||
const axiosError = error as {
|
||||
response?: { data?: { detail?: string } };
|
||||
message?: string;
|
||||
};
|
||||
return axiosError.response?.data?.detail || axiosError.message || fallback;
|
||||
}
|
||||
|
||||
type PreferencesValues = {
|
||||
order: boolean;
|
||||
}
|
||||
@@ -128,6 +162,10 @@ const ThemeSettingsCard = (): JSX.Element => {
|
||||
const themeColors = Object.keys(palettes);
|
||||
|
||||
const [order, setOrder] = useState<boolean>(true);
|
||||
const [useConversationContext, setUseConversationContext] = useState<boolean>(false);
|
||||
const [prefsLoading, setPrefsLoading] = useState<boolean>(true);
|
||||
const [contextSaving, setContextSaving] = useState<boolean>(false);
|
||||
const [prefsError, setPrefsError] = useState<string>('');
|
||||
const { updatePreferences } = useContext(PreferenceContext);
|
||||
|
||||
const handleConversationOrder = async ({ order }: PreferencesValues): Promise<void> => {
|
||||
@@ -141,17 +179,50 @@ const ThemeSettingsCard = (): JSX.Element => {
|
||||
}
|
||||
}
|
||||
|
||||
async function getConversationOrder() {
|
||||
async function getConversationPreferences() {
|
||||
setPrefsLoading(true);
|
||||
setPrefsError('');
|
||||
try {
|
||||
const { data, }: AxiosResponse<PreferencesType> = await axiosInstance.get(`/conversation_preferences`);
|
||||
const { data }: AxiosResponse<PreferencesType> = await axiosInstance.get(
|
||||
`/conversation_preferences`
|
||||
);
|
||||
setOrder(data.order);
|
||||
setUseConversationContext(Boolean(data.use_conversation_context));
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
setPrefsError(
|
||||
prefsErrorMessage(error, 'Could not load account preferences.')
|
||||
);
|
||||
} finally {
|
||||
setPrefsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const handleConversationContext = async (enabled: boolean): Promise<void> => {
|
||||
const previous = useConversationContext;
|
||||
setUseConversationContext(enabled);
|
||||
setContextSaving(true);
|
||||
setPrefsError('');
|
||||
try {
|
||||
const { data }: AxiosResponse<PreferencesType> = await axiosInstance.post(
|
||||
'/conversation_preferences',
|
||||
{ use_conversation_context: enabled }
|
||||
);
|
||||
setUseConversationContext(Boolean(data.use_conversation_context));
|
||||
} catch (error) {
|
||||
setUseConversationContext(previous);
|
||||
setPrefsError(
|
||||
prefsErrorMessage(
|
||||
error,
|
||||
'Could not update conversation context setting. Try again.'
|
||||
)
|
||||
);
|
||||
} finally {
|
||||
setContextSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getConversationOrder();
|
||||
getConversationPreferences();
|
||||
}, [])
|
||||
|
||||
const handleDarkMode = () => setDarkMode(dispatch, !darkMode);
|
||||
@@ -193,6 +264,7 @@ const ThemeSettingsCard = (): JSX.Element => {
|
||||
<Checkbox
|
||||
type="checkbox"
|
||||
checked={order}
|
||||
disabled={prefsLoading}
|
||||
onChange={() => {
|
||||
setOrder(!order);
|
||||
handleConversationOrder({ order: !order })
|
||||
@@ -202,6 +274,30 @@ const ThemeSettingsCard = (): JSX.Element => {
|
||||
</ToggleSwitch>
|
||||
</SettingRow>
|
||||
|
||||
<SettingRow>
|
||||
<SettingLabel>
|
||||
Use previous conversations
|
||||
<Tooltip title={CONTEXT_TOOLTIP}>
|
||||
<span>
|
||||
<InfoIcon aria-label={CONTEXT_TOOLTIP} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</SettingLabel>
|
||||
<ToggleSwitch>
|
||||
<Checkbox
|
||||
type="checkbox"
|
||||
checked={useConversationContext}
|
||||
disabled={prefsLoading || contextSaving}
|
||||
onChange={() => {
|
||||
handleConversationContext(!useConversationContext);
|
||||
}}
|
||||
/>
|
||||
<Slider />
|
||||
</ToggleSwitch>
|
||||
</SettingRow>
|
||||
|
||||
{prefsError ? <ErrorText role="alert">{prefsError}</ErrorText> : null}
|
||||
|
||||
</GlassCard>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -269,6 +269,7 @@ export interface AccountType {
|
||||
|
||||
export interface PreferencesType {
|
||||
order: boolean;
|
||||
use_conversation_context?: boolean;
|
||||
}
|
||||
|
||||
export class Account {
|
||||
|
||||
Reference in New Issue
Block a user