mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-09-20 00:01:32 +00:00
feat(UI): Tabbed interface for messages.
This commit is contained in:
@@ -26,38 +26,44 @@ function generateOpenSearchResponse(origin: string): NextResponse {
|
||||
export async function GET(request: Request) {
|
||||
// Check if a BASE_URL is explicitly configured
|
||||
const configBaseUrl = getBaseUrl();
|
||||
|
||||
|
||||
// If BASE_URL is configured, use it, otherwise detect from request
|
||||
if (configBaseUrl) {
|
||||
// Remove any trailing slashes for consistency
|
||||
let origin = configBaseUrl.replace(/\/+$/, '');
|
||||
return generateOpenSearchResponse(origin);
|
||||
}
|
||||
|
||||
|
||||
// Detect the correct origin, taking into account reverse proxy headers
|
||||
const url = new URL(request.url);
|
||||
let origin = url.origin;
|
||||
|
||||
|
||||
// Extract headers
|
||||
const headers = Object.fromEntries(request.headers);
|
||||
|
||||
|
||||
// Check for X-Forwarded-Host and related headers to handle reverse proxies
|
||||
if (headers['x-forwarded-host']) {
|
||||
// Determine protocol: prefer X-Forwarded-Proto, fall back to original or https
|
||||
const protocol = headers['x-forwarded-proto'] || url.protocol.replace(':', '');
|
||||
const protocol =
|
||||
headers['x-forwarded-proto'] || url.protocol.replace(':', '');
|
||||
// Build the correct public-facing origin
|
||||
origin = `${protocol}://${headers['x-forwarded-host']}`;
|
||||
|
||||
|
||||
// Handle non-standard ports if specified in X-Forwarded-Port
|
||||
if (headers['x-forwarded-port']) {
|
||||
const port = headers['x-forwarded-port'];
|
||||
// Don't append standard ports (80 for HTTP, 443 for HTTPS)
|
||||
if (!((protocol === 'http' && port === '80') || (protocol === 'https' && port === '443'))) {
|
||||
if (
|
||||
!(
|
||||
(protocol === 'http' && port === '80') ||
|
||||
(protocol === 'https' && port === '443')
|
||||
)
|
||||
) {
|
||||
origin = `${origin}:${port}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate and return the OpenSearch response
|
||||
return generateOpenSearchResponse(origin);
|
||||
}
|
||||
|
@@ -145,8 +145,6 @@ const Page = () => {
|
||||
string | null
|
||||
>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [automaticImageSearch, setAutomaticImageSearch] = useState(false);
|
||||
const [automaticVideoSearch, setAutomaticVideoSearch] = useState(false);
|
||||
const [automaticSuggestions, setAutomaticSuggestions] = useState(true);
|
||||
const [systemInstructions, setSystemInstructions] = useState<string>('');
|
||||
const [savingStates, setSavingStates] = useState<Record<string, boolean>>({});
|
||||
@@ -209,12 +207,6 @@ const Page = () => {
|
||||
setChatModels(data.chatModelProviders || {});
|
||||
setEmbeddingModels(data.embeddingModelProviders || {});
|
||||
|
||||
setAutomaticImageSearch(
|
||||
localStorage.getItem('autoImageSearch') === 'true',
|
||||
);
|
||||
setAutomaticVideoSearch(
|
||||
localStorage.getItem('autoVideoSearch') === 'true',
|
||||
);
|
||||
setAutomaticSuggestions(
|
||||
localStorage.getItem('autoSuggestions') !== 'false', // default to true if not set
|
||||
);
|
||||
@@ -372,11 +364,7 @@ const Page = () => {
|
||||
setConfig(data);
|
||||
}
|
||||
|
||||
if (key === 'automaticImageSearch') {
|
||||
localStorage.setItem('autoImageSearch', value.toString());
|
||||
} else if (key === 'automaticVideoSearch') {
|
||||
localStorage.setItem('autoVideoSearch', value.toString());
|
||||
} else if (key === 'automaticSuggestions') {
|
||||
if (key === 'automaticSuggestions') {
|
||||
localStorage.setItem('autoSuggestions', value.toString());
|
||||
} else if (key === 'chatModelProvider') {
|
||||
localStorage.setItem('chatModelProvider', value);
|
||||
@@ -449,90 +437,6 @@ const Page = () => {
|
||||
|
||||
<SettingsSection title="Automatic Search">
|
||||
<div className="flex flex-col space-y-4">
|
||||
<div className="flex items-center justify-between p-3 bg-light-secondary dark:bg-dark-secondary rounded-lg hover:bg-light-200 dark:hover:bg-dark-200 transition-colors">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-light-200 dark:bg-dark-200 rounded-lg">
|
||||
<ImagesIcon
|
||||
size={18}
|
||||
className="text-black/70 dark:text-white/70"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-black/90 dark:text-white/90 font-medium">
|
||||
Automatic Image Search
|
||||
</p>
|
||||
<p className="text-xs text-black/60 dark:text-white/60 mt-0.5">
|
||||
Automatically search for relevant images in chat
|
||||
responses
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={automaticImageSearch}
|
||||
onChange={(checked) => {
|
||||
setAutomaticImageSearch(checked);
|
||||
saveConfig('automaticImageSearch', checked);
|
||||
}}
|
||||
className={cn(
|
||||
automaticImageSearch
|
||||
? 'bg-[#24A0ED]'
|
||||
: 'bg-light-200 dark:bg-dark-200',
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none',
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
automaticImageSearch
|
||||
? 'translate-x-6'
|
||||
: 'translate-x-1',
|
||||
'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 bg-light-secondary dark:bg-dark-secondary rounded-lg hover:bg-light-200 dark:hover:bg-dark-200 transition-colors">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-light-200 dark:bg-dark-200 rounded-lg">
|
||||
<VideoIcon
|
||||
size={18}
|
||||
className="text-black/70 dark:text-white/70"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-black/90 dark:text-white/90 font-medium">
|
||||
Automatic Video Search
|
||||
</p>
|
||||
<p className="text-xs text-black/60 dark:text-white/60 mt-0.5">
|
||||
Automatically search for relevant videos in chat
|
||||
responses
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={automaticVideoSearch}
|
||||
onChange={(checked) => {
|
||||
setAutomaticVideoSearch(checked);
|
||||
saveConfig('automaticVideoSearch', checked);
|
||||
}}
|
||||
className={cn(
|
||||
automaticVideoSearch
|
||||
? 'bg-[#24A0ED]'
|
||||
: 'bg-light-200 dark:bg-dark-200',
|
||||
'relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none',
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
automaticVideoSearch
|
||||
? 'translate-x-6'
|
||||
: 'translate-x-1',
|
||||
'inline-block h-4 w-4 transform rounded-full bg-white transition-transform',
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-3 bg-light-secondary dark:bg-dark-secondary rounded-lg hover:bg-light-200 dark:hover:bg-dark-200 transition-colors">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-light-200 dark:bg-dark-200 rounded-lg">
|
||||
|
Reference in New Issue
Block a user