This commit is contained in:
Andision 2024-07-23 12:25:59 +07:00 committed by GitHub
commit 33a09d100f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 96 additions and 32 deletions

View File

@ -9,15 +9,15 @@ import {
OnDragEndResponder,
} from "@hello-pangea/dnd";
import { useChatStore } from "../store";
import { ChatSession, useChatStore } from "../store";
import Locale from "../locales";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { Path } from "../constant";
import { MaskAvatar } from "./mask";
import { Mask } from "../store/mask";
import { useRef, useEffect } from "react";
import { showConfirm } from "./ui-lib";
import { useRef, useEffect, useState } from "react";
import { showConfirm, SearchInput } from "./ui-lib";
import { useMobileScreen } from "../utils";
export function ChatItem(props: {
@ -102,7 +102,7 @@ export function ChatItem(props: {
);
}
export function ChatList(props: { narrow?: boolean }) {
export function ChatList(props: { narrow?: boolean; search: string }) {
const [sessions, selectedIndex, selectSession, moveSession] = useChatStore(
(state) => [
state.sessions,
@ -131,6 +131,24 @@ export function ChatList(props: { narrow?: boolean }) {
moveSession(source.index, destination.index);
};
function haveSearchKeyword(item: ChatSession): boolean {
if (props.search.length === 0) {
return true;
}
let foundKeyword = false;
item.messages.forEach((message) => {
// console.log(chatListSearch, message.content, message.content.includes(chatListSearch))
if (message.content.includes(props.search)) {
foundKeyword = true;
return;
}
});
return foundKeyword;
}
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="chat-list">
@ -140,31 +158,34 @@ export function ChatList(props: { narrow?: boolean }) {
ref={provided.innerRef}
{...provided.droppableProps}
>
{sessions.map((item, i) => (
<ChatItem
title={item.topic}
time={new Date(item.lastUpdate).toLocaleString()}
count={item.messages.length}
key={item.id}
id={item.id}
index={i}
selected={i === selectedIndex}
onClick={() => {
navigate(Path.Chat);
selectSession(i);
}}
onDelete={async () => {
if (
(!props.narrow && !isMobileScreen) ||
(await showConfirm(Locale.Home.DeleteChat))
) {
chatStore.deleteSession(i);
}
}}
narrow={props.narrow}
mask={item.mask}
/>
))}
{sessions.map(
(item, i) =>
haveSearchKeyword(item) && (
<ChatItem
title={item.topic}
time={new Date(item.lastUpdate).toLocaleString()}
count={item.messages.length}
key={item.id}
id={item.id}
index={i}
selected={i === selectedIndex}
onClick={() => {
navigate(Path.Chat);
selectSession(i);
}}
onDelete={async () => {
if (
(!props.narrow && !isMobileScreen) ||
(await showConfirm(Locale.Home.DeleteChat))
) {
chatStore.deleteSession(i);
}
}}
narrow={props.narrow}
mask={item.mask}
/>
),
)}
{provided.placeholder}
</div>
)}

View File

@ -230,6 +230,11 @@
white-space: nowrap;
}
.chat-list-search {
padding: 10px 0px;
margin-bottom: 10px;
}
.narrow-sidebar {
.sidebar-title,
.sidebar-sub-title {

View File

@ -1,4 +1,4 @@
import { useEffect, useRef, useMemo } from "react";
import { useEffect, useRef, useMemo, useState } from "react";
import styles from "./home.module.scss";
@ -29,7 +29,7 @@ import {
import { Link, useNavigate } from "react-router-dom";
import { isIOS, useMobileScreen } from "../utils";
import dynamic from "next/dynamic";
import { showConfirm, showToast } from "./ui-lib";
import { SearchInput, showConfirm, showToast } from "./ui-lib";
const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, {
loading: () => null,
@ -141,6 +141,8 @@ export function SideBar(props: { className?: string }) {
[isMobileScreen],
);
const [chatListSearch, setChatListSearch] = useState("");
useHotKey();
return (
@ -188,6 +190,16 @@ export function SideBar(props: { className?: string }) {
/>
</div>
<div className={styles["chat-list-search"]}>
<SearchInput
value={chatListSearch}
onChange={(e) => {
setChatListSearch(e.currentTarget.value);
}}
placeholder={Locale.Home.Search}
></SearchInput>
</div>
<div
className={styles["sidebar-body"]}
onClick={(e) => {
@ -196,7 +208,7 @@ export function SideBar(props: { className?: string }) {
}
}}
>
<ChatList narrow={shouldNarrow} />
<ChatList narrow={shouldNarrow} search={chatListSearch} />
</div>
<div className={styles["sidebar-tail"]}>

View File

@ -275,6 +275,20 @@ export function PasswordInput(props: HTMLProps<HTMLInputElement>) {
);
}
export function SearchInput(props: HTMLProps<HTMLInputElement>) {
const [visible, setVisible] = useState(false);
function changeVisibility() {
setVisible(!visible);
}
return (
<div className={"search-input-container"}>
<input {...props} type="text" className={"search-input"} />
</div>
);
}
export function Select(
props: React.DetailedHTMLProps<
React.SelectHTMLAttributes<HTMLSelectElement>,

View File

@ -124,6 +124,7 @@ const cn = {
DeleteChat: "确认删除选中的对话?",
DeleteToast: "已删除会话",
Revert: "撤销",
Search: "输入筛选的关键词",
},
Settings: {
Title: "设置",

View File

@ -127,6 +127,7 @@ const en: LocaleType = {
DeleteChat: "Confirm to delete the selected conversation?",
DeleteToast: "Chat Deleted",
Revert: "Revert",
Search: "Enter filter keywords",
},
Settings: {
Title: "Settings",

View File

@ -344,6 +344,16 @@ pre {
}
}
.search-input-container {
display: flex;
justify-content: center;
.search-input {
min-width: 99%;
text-align: left;
}
}
.user-avatar {
height: 30px;
min-height: 30px;