mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 03:20:46 +02:00
Prettier 2: Electric Boogaloo (#6113)
# Description of Changes When I added Prettier formatting in #6052, my aim was to use just the default settings in Prettier. Turns out, Prettier looks _really hard_ for any config files if it's not explicitly given one, which means that if a developer has some sort of Prettier config file lying around on their system, Prettier might find it and use it. Also, Prettier changes its defaults based on stuff in `.editorconfig` without any good way of disabling that behaviour explicitly in its config file. To solve both of these issues, I've introduced a `.prettierrc` file which sets Prettier's defaults explicitly, and then reformatted all our code _again_ in Prettier's actual default settings. This should achieve the aim of #6052 and remove the possibility for it breaking on different dev computers.
This commit is contained in:
@@ -4,9 +4,16 @@ import { ChatProvider } from "@app/components/chat/ChatContext";
|
||||
|
||||
export type { AppProvidersProps };
|
||||
|
||||
export function AppProviders({ children, appConfigRetryOptions, appConfigProviderProps }: AppProvidersProps) {
|
||||
export function AppProviders({
|
||||
children,
|
||||
appConfigRetryOptions,
|
||||
appConfigProviderProps,
|
||||
}: AppProvidersProps) {
|
||||
return (
|
||||
<ProprietaryAppProviders appConfigRetryOptions={appConfigRetryOptions} appConfigProviderProps={appConfigProviderProps}>
|
||||
<ProprietaryAppProviders
|
||||
appConfigRetryOptions={appConfigRetryOptions}
|
||||
appConfigProviderProps={appConfigProviderProps}
|
||||
>
|
||||
<ChatProvider>{children}</ChatProvider>
|
||||
</ProprietaryAppProviders>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { createContext, useContext, useReducer, useCallback, useRef, type ReactNode } from "react";
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useReducer,
|
||||
useCallback,
|
||||
useRef,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import { useAllFiles } from "@app/contexts/FileContext";
|
||||
import { getAuthHeaders } from "@app/services/apiClientSetup";
|
||||
|
||||
@@ -82,7 +89,10 @@ function formatWorkflowResponse(data: AiWorkflowResponse): string {
|
||||
case "not_found":
|
||||
return data.reason ?? "I couldn't find the requested information.";
|
||||
case "unsupported_capability":
|
||||
return data.message ?? `Unsupported capability: ${data.capability ?? "unknown"}`;
|
||||
return (
|
||||
data.message ??
|
||||
`Unsupported capability: ${data.capability ?? "unknown"}`
|
||||
);
|
||||
case "cannot_continue":
|
||||
return data.reason ?? "Something went wrong and I can't continue.";
|
||||
case "plan":
|
||||
@@ -91,9 +101,13 @@ function formatWorkflowResponse(data: AiWorkflowResponse): string {
|
||||
: JSON.stringify(data.steps, null, 2);
|
||||
case "need_content":
|
||||
case "tool_call":
|
||||
return data.rationale ?? data.summary ?? `Processing (${data.outcome})...`;
|
||||
return (
|
||||
data.rationale ?? data.summary ?? `Processing (${data.outcome})...`
|
||||
);
|
||||
default:
|
||||
return data.answer ?? data.summary ?? data.message ?? JSON.stringify(data);
|
||||
return (
|
||||
data.answer ?? data.summary ?? data.message ?? JSON.stringify(data)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +192,10 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
|
||||
const toggleOpen = useCallback(() => dispatch({ type: "TOGGLE_OPEN" }), []);
|
||||
const setOpen = useCallback((open: boolean) => dispatch({ type: "SET_OPEN", open }), []);
|
||||
const setOpen = useCallback(
|
||||
(open: boolean) => dispatch({ type: "SET_OPEN", open }),
|
||||
[],
|
||||
);
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async (content: string) => {
|
||||
@@ -220,7 +237,10 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
await consumeSSEStream(response, {
|
||||
onProgress: (data) => {
|
||||
dispatch({ type: "SET_PROGRESS", phase: data.phase as AiWorkflowPhase });
|
||||
dispatch({
|
||||
type: "SET_PROGRESS",
|
||||
phase: data.phase as AiWorkflowPhase,
|
||||
});
|
||||
},
|
||||
onResult: (data) => {
|
||||
receivedResult = true;
|
||||
@@ -262,7 +282,8 @@ export function ChatProvider({ children }: { children: ReactNode }) {
|
||||
message: {
|
||||
id: crypto.randomUUID(),
|
||||
role: "assistant",
|
||||
content: "Failed to get a response. The AI engine may not be available yet.",
|
||||
content:
|
||||
"Failed to get a response. The AI engine may not be available yet.",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--mantine-color-body);
|
||||
border-left: 1px solid var(--border-subtle, var(--mantine-color-default-border));
|
||||
border-left: 1px solid
|
||||
var(--border-subtle, var(--mantine-color-default-border));
|
||||
z-index: 999;
|
||||
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@@ -25,7 +26,8 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid var(--border-subtle, var(--mantine-color-default-border));
|
||||
border-bottom: 1px solid
|
||||
var(--border-subtle, var(--mantine-color-default-border));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +40,8 @@
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
border-top: 1px solid var(--border-subtle, var(--mantine-color-default-border));
|
||||
border-top: 1px solid
|
||||
var(--border-subtle, var(--mantine-color-default-border));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
import { useRef, useEffect, useState, type KeyboardEvent } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ActionIcon, ScrollArea, TextInput, Stack, Text, Paper, Box, Transition, Loader, Group } from "@mantine/core";
|
||||
import {
|
||||
ActionIcon,
|
||||
ScrollArea,
|
||||
TextInput,
|
||||
Stack,
|
||||
Text,
|
||||
Paper,
|
||||
Box,
|
||||
Transition,
|
||||
Loader,
|
||||
Group,
|
||||
} from "@mantine/core";
|
||||
import SendIcon from "@mui/icons-material/Send";
|
||||
import ChatBubbleOutlineIcon from "@mui/icons-material/ChatBubbleOutline";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { useChat } from "@app/components/chat/ChatContext";
|
||||
import "@app/components/chat/ChatPanel.css";
|
||||
|
||||
function ChatMessageBubble({ role, content }: { role: "user" | "assistant"; content: string }) {
|
||||
function ChatMessageBubble({
|
||||
role,
|
||||
content,
|
||||
}: {
|
||||
role: "user" | "assistant";
|
||||
content: string;
|
||||
}) {
|
||||
return (
|
||||
<div className={`chat-message chat-message-${role}`}>
|
||||
<Paper className={`chat-bubble chat-bubble-${role}`} p="xs" radius="md">
|
||||
@@ -21,14 +38,24 @@ function ChatMessageBubble({ role, content }: { role: "user" | "assistant"; cont
|
||||
|
||||
export function ChatPanel() {
|
||||
const { t } = useTranslation();
|
||||
const { messages, isOpen, isLoading, progressPhase, toggleOpen, sendMessage } = useChat();
|
||||
const {
|
||||
messages,
|
||||
isOpen,
|
||||
isLoading,
|
||||
progressPhase,
|
||||
toggleOpen,
|
||||
sendMessage,
|
||||
} = useChat();
|
||||
const [input, setInput] = useState("");
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
scrollRef.current.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" });
|
||||
scrollRef.current.scrollTo({
|
||||
top: scrollRef.current.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}
|
||||
}, [messages]);
|
||||
|
||||
@@ -78,7 +105,12 @@ export function ChatPanel() {
|
||||
<Text fw={600} size="sm">
|
||||
AI Assistant
|
||||
</Text>
|
||||
<ActionIcon variant="subtle" size="sm" onClick={toggleOpen} aria-label="Close chat">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={toggleOpen}
|
||||
aria-label="Close chat"
|
||||
>
|
||||
<CloseIcon sx={{ fontSize: 16 }} />
|
||||
</ActionIcon>
|
||||
</div>
|
||||
@@ -88,19 +120,30 @@ export function ChatPanel() {
|
||||
<Stack gap="sm" p="sm">
|
||||
{messages.length === 0 && (
|
||||
<Text size="sm" c="dimmed" ta="center" py="xl">
|
||||
Ask a question about your documents or get help with PDF tools.
|
||||
Ask a question about your documents or get help with PDF
|
||||
tools.
|
||||
</Text>
|
||||
)}
|
||||
{messages.map((msg) => (
|
||||
<ChatMessageBubble key={msg.id} role={msg.role} content={msg.content} />
|
||||
<ChatMessageBubble
|
||||
key={msg.id}
|
||||
role={msg.role}
|
||||
content={msg.content}
|
||||
/>
|
||||
))}
|
||||
{isLoading && (
|
||||
<div className="chat-message chat-message-assistant">
|
||||
<Paper className="chat-bubble chat-bubble-assistant" p="xs" radius="md">
|
||||
<Paper
|
||||
className="chat-bubble chat-bubble-assistant"
|
||||
p="xs"
|
||||
radius="md"
|
||||
>
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<Loader size="xs" type="dots" />
|
||||
<Text size="sm" c="dimmed">
|
||||
{progressPhase ? t(`chat.progress.${progressPhase}`) : t("chat.progress.thinking")}
|
||||
{progressPhase
|
||||
? t(`chat.progress.${progressPhase}`)
|
||||
: t("chat.progress.thinking")}
|
||||
</Text>
|
||||
</Group>
|
||||
</Paper>
|
||||
|
||||
@@ -8,5 +8,12 @@
|
||||
"@core/*": ["src/core/*"]
|
||||
}
|
||||
},
|
||||
"include": ["../global.d.ts", "../*.js", "../*.ts", "../*.tsx", "../core/setupTests.ts", "."]
|
||||
"include": [
|
||||
"../global.d.ts",
|
||||
"../*.js",
|
||||
"../*.ts",
|
||||
"../*.tsx",
|
||||
"../core/setupTests.ts",
|
||||
"."
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user