mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 02:05:57 +08:00
feat: session manger (#867)
* feat: init session manger * feat: persist selected app to localStorage - Save app selection when switching providers - Restore last selected app on page load * feat: persist current view to localStorage - Save view selection when switching tabs - Restore last selected view on page load * styles: update ui * feat: Improve macOS Terminal activation and refactor Kitty launch to use command with user's default shell. * fix: session view * feat: toc * feat: Implement FlexSearch for improved session search functionality. * feat: Redesign session manager search and filter UI for a more compact and dynamic experience. * refactor: modularize session manager by extracting components and utility functions into dedicated files. * feat: Enhance session terminal launching with support for iTerm2, Ghostty, WezTerm, and Alacritty, including UI and custom configuration options. * feat: Conditionally render terminal selection and resume session buttons only on macOS.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { Copy } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { SessionMessage } from "@/types";
|
||||
import { formatTimestamp, getRoleLabel, getRoleTone } from "./utils";
|
||||
|
||||
interface SessionMessageItemProps {
|
||||
message: SessionMessage;
|
||||
index: number;
|
||||
isActive: boolean;
|
||||
setRef: (el: HTMLDivElement | null) => void;
|
||||
onCopy: (content: string) => void;
|
||||
}
|
||||
|
||||
export function SessionMessageItem({
|
||||
message,
|
||||
isActive,
|
||||
setRef,
|
||||
onCopy,
|
||||
}: SessionMessageItemProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setRef}
|
||||
className={cn(
|
||||
"rounded-lg border px-3 py-2.5 relative group transition-all",
|
||||
message.role.toLowerCase() === "user"
|
||||
? "bg-primary/5 border-primary/20 ml-8"
|
||||
: message.role.toLowerCase() === "assistant"
|
||||
? "bg-blue-500/5 border-blue-500/20 mr-8"
|
||||
: "bg-muted/40 border-border/60",
|
||||
isActive && "ring-2 ring-primary ring-offset-2"
|
||||
)}
|
||||
>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="absolute top-2 right-2 size-6 opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
onClick={() => onCopy(message.content)}
|
||||
>
|
||||
<Copy className="size-3" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{t("sessionManager.copyMessage", {
|
||||
defaultValue: "复制内容",
|
||||
})}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<div className="flex items-center justify-between text-xs mb-1.5 pr-6">
|
||||
<span className={cn("font-semibold", getRoleTone(message.role))}>
|
||||
{getRoleLabel(message.role)}
|
||||
</span>
|
||||
{message.ts && (
|
||||
<span className="text-muted-foreground">
|
||||
{formatTimestamp(message.ts)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="whitespace-pre-wrap text-sm leading-relaxed">
|
||||
{message.content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user