mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-13 02:18:16 +01:00
improving context
This commit is contained in:
@@ -5145,8 +5145,7 @@
|
||||
"title": "Stirling PDF Bot",
|
||||
"alphaBadge": "Alpha",
|
||||
"alphaTitle": "Experimental feature",
|
||||
"alphaDescription": "This Chatbot feature is in currently in alpha and is subject to change. Image-based content is not supported yet. Responses may be imperfect, so double-check important answers.",
|
||||
"acceptAlphaLabel": "I understand this feature is experimental and image content is not supported yet.",
|
||||
"alphaDescription": "Chatbot is in currently in alpha and is subject to change. Responses may be imperfect, please check responses.",
|
||||
"fileLabel": "Document to query",
|
||||
"filePlaceholder": "Select an uploaded PDF",
|
||||
"noFiles": "Upload a PDF from File Manager to start chatting.",
|
||||
@@ -5193,6 +5192,14 @@
|
||||
"noTextTitle": "No text detected in this PDF",
|
||||
"noTextBody": "We could not find selectable text in this document. Would you like to run OCR to convert scanned pages into text?",
|
||||
"noTextDismiss": "Maybe later",
|
||||
"noTextRunOcr": "Run OCR and retry"
|
||||
"noTextRunOcr": "Run OCR and retry",
|
||||
"usage": {
|
||||
"limitReachedTitle": "Chatbot limit reached",
|
||||
"limitReachedBody": "You have exceeded the current monthly allocation for the chatbot. Further responses may be throttled.",
|
||||
"nearingLimitTitle": "Approaching usage limit",
|
||||
"nearingLimitBody": "You are nearing your monthly chatbot allocation. Consider limiting very large requests."
|
||||
},
|
||||
"autoSyncInfo": "Selected documents are synced automatically when the chatbot opens.",
|
||||
"autoSyncPrompt": "Acknowledge the alpha notice to start syncing automatically."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react';
|
||||
import {
|
||||
ActionIcon,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
@@ -13,14 +12,12 @@ import {
|
||||
Switch,
|
||||
Text,
|
||||
Textarea,
|
||||
Tooltip,
|
||||
} from '@mantine/core';
|
||||
import { useMediaQuery, useViewportSize } from '@mantine/hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SmartToyRoundedIcon from '@mui/icons-material/SmartToyRounded';
|
||||
import WarningAmberRoundedIcon from '@mui/icons-material/WarningAmberRounded';
|
||||
import SendRoundedIcon from '@mui/icons-material/SendRounded';
|
||||
import RefreshRoundedIcon from '@mui/icons-material/RefreshRounded';
|
||||
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
||||
|
||||
import { useChatbot } from '@app/contexts/ChatbotContext';
|
||||
@@ -47,8 +44,6 @@ interface ChatMessage {
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
const ALPHA_ACK_KEY = 'stirling.chatbot.alphaAck';
|
||||
|
||||
function createMessageId() {
|
||||
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
||||
return crypto.randomUUID();
|
||||
@@ -68,7 +63,6 @@ const ChatbotDrawer = () => {
|
||||
const { show } = useToast();
|
||||
const files = selectors.getFiles();
|
||||
const [selectedFileId, setSelectedFileId] = useState<string | undefined>();
|
||||
const [alphaAccepted, setAlphaAccepted] = useState(false);
|
||||
const [runOcr, setRunOcr] = useState(false);
|
||||
const [isStartingSession, setIsStartingSession] = useState(false);
|
||||
const [isSendingMessage, setIsSendingMessage] = useState(false);
|
||||
@@ -94,11 +88,6 @@ const ChatbotDrawer = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const storedAck = typeof window !== 'undefined'
|
||||
? window.localStorage.getItem(ALPHA_ACK_KEY) === 'true'
|
||||
: false;
|
||||
setAlphaAccepted(storedAck);
|
||||
|
||||
if (preferredFileId) {
|
||||
setSelectedFileId(preferredFileId);
|
||||
setPreferredFileId(undefined);
|
||||
@@ -161,6 +150,8 @@ const ChatbotDrawer = () => {
|
||||
setContextStats(null);
|
||||
setMessages([]);
|
||||
setWarnings([]);
|
||||
setPendingOcrRetry(false);
|
||||
setNoTextModalOpen(false);
|
||||
}
|
||||
}, [sessionInfo, selectedFileId]);
|
||||
|
||||
@@ -192,17 +183,6 @@ const ChatbotDrawer = () => {
|
||||
};
|
||||
}, [isMobile, isOpen, sidebarRefs.toolPanelRef]);
|
||||
|
||||
const handleAlphaAccept = (checked: boolean) => {
|
||||
setAlphaAccepted(checked);
|
||||
if (typeof window !== 'undefined') {
|
||||
if (checked) {
|
||||
window.localStorage.setItem(ALPHA_ACK_KEY, 'true');
|
||||
} else {
|
||||
window.localStorage.removeItem(ALPHA_ACK_KEY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const withStatus = async <T,>(label: string, fn: () => Promise<T>): Promise<T> => {
|
||||
setStatusMessage(label);
|
||||
try {
|
||||
@@ -228,14 +208,6 @@ const ChatbotDrawer = () => {
|
||||
if (!ensureFileSelected() || !selectedFile) {
|
||||
return;
|
||||
}
|
||||
if (!alphaAccepted) {
|
||||
show({
|
||||
alertType: 'neutral',
|
||||
title: t('chatbot.toasts.ackTitle', 'Accept alpha notice'),
|
||||
body: t('chatbot.toasts.ackBody', 'Please acknowledge the alpha warning before starting.'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
setIsStartingSession(true);
|
||||
try {
|
||||
let workingFile: File = selectedFile;
|
||||
@@ -271,7 +243,7 @@ const ChatbotDrawer = () => {
|
||||
text: extractionResult.text,
|
||||
metadata,
|
||||
ocrRequested: shouldRunOcr,
|
||||
warningsAccepted: alphaAccepted,
|
||||
warningsAccepted: true,
|
||||
};
|
||||
|
||||
const response = await withStatus(
|
||||
@@ -302,6 +274,36 @@ const ChatbotDrawer = () => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!isOpen ||
|
||||
!selectedFile ||
|
||||
sessionInfo ||
|
||||
isStartingSession ||
|
||||
pendingOcrRetry ||
|
||||
noTextModalOpen
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
handleSessionStart().catch((error) => {
|
||||
if (!cancelled) {
|
||||
console.error('[Chatbot] Auto-sync failed', error);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [isOpen, selectedFile, sessionInfo, isStartingSession, pendingOcrRetry, noTextModalOpen, runOcr]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!sessionInfo) {
|
||||
return;
|
||||
}
|
||||
setSessionInfo(null);
|
||||
setContextStats(null);
|
||||
}, [runOcr]);
|
||||
|
||||
const handleSendMessage = async () => {
|
||||
if (!sessionInfo) {
|
||||
show({
|
||||
@@ -495,25 +497,6 @@ const ChatbotDrawer = () => {
|
||||
transitionProps={{ transition: 'slide-left', duration: 200 }}
|
||||
>
|
||||
<Stack gap="sm" h="100%" style={{ minHeight: 0 }}>
|
||||
<Box
|
||||
p="sm"
|
||||
style={{
|
||||
border: '1px solid var(--border-subtle)',
|
||||
borderRadius: 8,
|
||||
backgroundColor: 'var(--bg-subtle)',
|
||||
display: 'flex',
|
||||
gap: '0.5rem',
|
||||
alignItems: 'flex-start',
|
||||
}}
|
||||
>
|
||||
<WarningAmberRoundedIcon fontSize="small" style={{ color: 'var(--text-warning)' }} />
|
||||
<Box>
|
||||
<Text fw={600}>{t('chatbot.alphaTitle', 'Experimental feature')}</Text>
|
||||
<Text size="sm">
|
||||
{t('chatbot.alphaDescription', 'This chatbot is in alpha. It currently ignores images and may produce inaccurate answers. Your PDF text stays local until you confirm you want to chat.')}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Group align="flex-end" justify="space-between" gap="md" wrap="wrap">
|
||||
<Select
|
||||
@@ -526,11 +509,6 @@ const ChatbotDrawer = () => {
|
||||
style={{ flex: '1 1 200px' }}
|
||||
/>
|
||||
<Stack gap={4} style={{ minWidth: 160 }}>
|
||||
<Switch
|
||||
checked={alphaAccepted}
|
||||
label={t('chatbot.acceptAlphaLabel', 'Alpha notice acknowledged')}
|
||||
onChange={(event) => handleAlphaAccept(event.currentTarget.checked)}
|
||||
/>
|
||||
<Switch
|
||||
checked={runOcr}
|
||||
onChange={(event) => setRunOcr(event.currentTarget.checked)}
|
||||
@@ -539,19 +517,6 @@ const ChatbotDrawer = () => {
|
||||
</Stack>
|
||||
</Group>
|
||||
|
||||
<Button
|
||||
fullWidth
|
||||
variant="filled"
|
||||
leftSection={<RefreshRoundedIcon fontSize="small" />}
|
||||
loading={isStartingSession}
|
||||
onClick={() => handleSessionStart()}
|
||||
disabled={!selectedFile || !alphaAccepted}
|
||||
>
|
||||
{sessionInfo
|
||||
? t('chatbot.refreshButton', 'Re-sync document')
|
||||
: t('chatbot.startButton', 'Send document to chat')}
|
||||
</Button>
|
||||
|
||||
{statusMessage && (
|
||||
<Box
|
||||
p="sm"
|
||||
@@ -596,6 +561,28 @@ const ChatbotDrawer = () => {
|
||||
</Group>
|
||||
</Box>
|
||||
))}
|
||||
{isOpen && (
|
||||
<Box
|
||||
p="sm"
|
||||
bg="var(--bg-muted)"
|
||||
style={{ borderRadius: 12, border: '1px solid var(--border-subtle)' }}
|
||||
>
|
||||
<Group gap="xs" align="flex-start">
|
||||
<WarningAmberRoundedIcon fontSize="small" style={{ color: 'var(--text-warning)' }} />
|
||||
<Box>
|
||||
<Text size="sm" fw={600}>
|
||||
{t('chatbot.alphaTitle', 'Experimental feature')}
|
||||
</Text>
|
||||
<Text size="sm">
|
||||
{t(
|
||||
'chatbot.alphaDescription',
|
||||
'This chatbot is in alpha. It currently ignores images and may produce inaccurate answers.'
|
||||
)}
|
||||
</Text>
|
||||
</Box>
|
||||
</Group>
|
||||
</Box>
|
||||
)}
|
||||
{messages.length === 0 && (
|
||||
<Text size="sm" c="dimmed">
|
||||
{t('chatbot.emptyState', 'Ask a question about your PDF to start the conversation.')}
|
||||
|
||||
@@ -7,14 +7,10 @@ import LocalIcon from '@app/components/shared/LocalIcon';
|
||||
import { Tooltip } from '@app/components/shared/Tooltip';
|
||||
import { SearchInterface } from '@app/components/viewer/SearchInterface';
|
||||
import ViewerAnnotationControls from '@app/components/shared/rightRail/ViewerAnnotationControls';
|
||||
import { useFileState } from '@app/contexts/FileContext';
|
||||
|
||||
export function useViewerRightRailButtons() {
|
||||
const { t } = useTranslation();
|
||||
const viewer = useViewer();
|
||||
const { selectors } = useFileState();
|
||||
const filesSignature = selectors.getFilesSignature();
|
||||
const files = useMemo(() => selectors.getFiles(), [selectors, filesSignature]);
|
||||
const [isPanning, setIsPanning] = useState<boolean>(() => viewer.getPanState()?.isPanning ?? false);
|
||||
|
||||
// Lift i18n labels out of memo for clarity
|
||||
|
||||
Reference in New Issue
Block a user