feat: conditionally render "Compare" button based on active checkpoint and lora selection, improve fallback title generation, and update default settings
This commit is contained in:
parent
571959e383
commit
e59ef60a5c
5 changed files with 41 additions and 19 deletions
|
|
@ -174,7 +174,8 @@ function InlineSidebar({
|
|||
function TopBarActions({
|
||||
onNewThread,
|
||||
onNewCompare,
|
||||
}: { onNewThread: () => void; onNewCompare: () => void }) {
|
||||
showCompare,
|
||||
}: { onNewThread: () => void; onNewCompare: () => void; showCompare: boolean }) {
|
||||
const { state } = useSidebar();
|
||||
if (state !== "collapsed") {
|
||||
return null;
|
||||
|
|
@ -189,14 +190,16 @@ function TopBarActions({
|
|||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">New Chat</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<Button variant="ghost" size="icon-sm" onClick={onNewCompare}>
|
||||
<HugeiconsIcon icon={ColumnInsertIcon} strokeWidth={2} />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">Compare</TooltipContent>
|
||||
</Tooltip>
|
||||
{showCompare ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild={true}>
|
||||
<Button variant="ghost" size="icon-sm" onClick={onNewCompare}>
|
||||
<HugeiconsIcon icon={ColumnInsertIcon} strokeWidth={2} />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom">Compare</TooltipContent>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -215,6 +218,11 @@ export function ChatPage(): ReactElement {
|
|||
const lorasFromStore = useChatRuntimeStore((state) => state.loras);
|
||||
const modelsError = useChatRuntimeStore((state) => state.modelsError);
|
||||
const { refresh, selectModel, ejectModel } = useChatModelRuntime();
|
||||
const canCompare = useMemo(() => {
|
||||
const selected = inferenceParams.checkpoint;
|
||||
if (!selected) return false;
|
||||
return lorasFromStore.some((lora) => lora.id === selected);
|
||||
}, [inferenceParams.checkpoint, lorasFromStore]);
|
||||
|
||||
const handleCheckpointChange = useCallback(
|
||||
(value: string, meta?: { isLora: boolean }) => {
|
||||
|
|
@ -277,6 +285,7 @@ export function ChatPage(): ReactElement {
|
|||
onSelect={setView}
|
||||
onNewThread={handleNewThread}
|
||||
onNewCompare={handleNewCompare}
|
||||
showCompare={canCompare}
|
||||
/>
|
||||
</InlineSidebar>
|
||||
|
||||
|
|
@ -287,6 +296,7 @@ export function ChatPage(): ReactElement {
|
|||
<TopBarActions
|
||||
onNewThread={handleNewThread}
|
||||
onNewCompare={handleNewCompare}
|
||||
showCompare={canCompare}
|
||||
/>
|
||||
<ModelSelector
|
||||
models={models}
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ export function ChatSettingsPanel({
|
|||
<CollapsibleSection
|
||||
icon={SlidersHorizontalIcon}
|
||||
label="Sampling"
|
||||
defaultOpen={true}
|
||||
defaultOpen={false}
|
||||
>
|
||||
<div className="flex flex-col gap-5">
|
||||
<ParamSlider
|
||||
|
|
|
|||
|
|
@ -225,6 +225,14 @@ async function generateTitleWithModel(payload: {
|
|||
|
||||
const inflightTitleByKey = new Set<string>();
|
||||
|
||||
function fallbackTitleFromUserText(userText: string): string {
|
||||
const firstLine = (userText || "").split(/\r?\n/, 1)[0] ?? "";
|
||||
const cleaned = firstLine.replace(/\s+/g, " ").trim();
|
||||
const max = 48;
|
||||
if (!cleaned) return "New Chat";
|
||||
return cleaned.slice(0, max) + (cleaned.length > max ? "..." : "");
|
||||
}
|
||||
|
||||
function toThreadMessage(m: MessageRecord): ThreadMessage {
|
||||
const base = {
|
||||
id: m.id,
|
||||
|
|
@ -342,7 +350,7 @@ function createDexieAdapter(
|
|||
const userText = extractTextParts(firstUser) || "New Chat";
|
||||
|
||||
if (!autoTitle) {
|
||||
const title = userText.slice(0, 60) + (userText.length > 60 ? "..." : "");
|
||||
const title = fallbackTitleFromUserText(userText);
|
||||
await db.threads.update(remoteId, { title });
|
||||
if (pairId) {
|
||||
const paired = await db.threads
|
||||
|
|
@ -394,7 +402,7 @@ function createDexieAdapter(
|
|||
(await generateTitleWithModel({
|
||||
userText,
|
||||
})) ||
|
||||
(userText.slice(0, 60) + (userText.length > 60 ? "..." : ""));
|
||||
fallbackTitleFromUserText(userText);
|
||||
|
||||
await db.threads.update(remoteId, { title });
|
||||
if (pairId) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export const useChatRuntimeStore = create<ChatRuntimeStore>((set) => ({
|
|||
loras: [],
|
||||
warmingByThreadId: {},
|
||||
runningByThreadId: {},
|
||||
autoTitle: loadBool(AUTO_TITLE_KEY, true),
|
||||
autoTitle: loadBool(AUTO_TITLE_KEY, false),
|
||||
modelsError: null,
|
||||
setParams: (params) => set({ params }),
|
||||
setModels: (models) => set({ models }),
|
||||
|
|
|
|||
|
|
@ -62,11 +62,13 @@ export function ThreadSidebar({
|
|||
onSelect,
|
||||
onNewThread,
|
||||
onNewCompare,
|
||||
showCompare,
|
||||
}: {
|
||||
view: ChatView;
|
||||
onSelect: (view: ChatView) => void;
|
||||
onNewThread: () => void;
|
||||
onNewCompare: () => void;
|
||||
showCompare: boolean;
|
||||
}) {
|
||||
const allThreads = useLiveQuery(
|
||||
() => db.threads.orderBy("createdAt").reverse().toArray(),
|
||||
|
|
@ -112,12 +114,14 @@ export function ThreadSidebar({
|
|||
<span>New Chat</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton onClick={onNewCompare}>
|
||||
<HugeiconsIcon icon={ColumnInsertIcon} />
|
||||
<span>Compare</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
{showCompare ? (
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton onClick={onNewCompare}>
|
||||
<HugeiconsIcon icon={ColumnInsertIcon} />
|
||||
<span>Compare</span>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
) : null}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue