Skip to content

Commit

Permalink
feat: add market land feature
Browse files Browse the repository at this point in the history
  • Loading branch information
zmh-program committed Mar 18, 2024
1 parent 5c42d33 commit 4b50ab2
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 18 deletions.
2 changes: 1 addition & 1 deletion app/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "chatnio",
"version": "3.10.7"
"version": "3.10.8"
},
"tauri": {
"allowlist": {
Expand Down
3 changes: 1 addition & 2 deletions app/src/assets/pages/home.less
Original file line number Diff line number Diff line change
Expand Up @@ -759,8 +759,7 @@
width: 100%;
color: hsl(var(--text));
white-space: pre-wrap;
scrollbar-width: thin;
padding-right: 3rem;
padding-right: 3.25rem;

&.align {
text-align: center;
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/home/ChatWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function ChatWrapper() {
<SettingsAction />
</div>
<div className={`input-wrapper`}>
<div className={`chat-box`}>
<div className={`chat-box no-scrollbar`}>
<ChatInput
className={cn(align && "align")}
target={target}
Expand Down
4 changes: 4 additions & 0 deletions app/src/components/home/ModelMarket.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ function getTags(model: Model): string[] {
return raw;
}

export function getModelAvatar(avatar: string) {
return useMemo(() => (isUrl(avatar) ? avatar : `/icons/${avatar}`), [avatar]);
}

function SearchBar({ value, onChange }: SearchBarProps) {
const { t } = useTranslation();

Expand Down
97 changes: 92 additions & 5 deletions app/src/components/home/assemblies/ChatAction.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import { openMarket, openMask, selectWeb, toggleWeb } from "@/store/chat.ts";
import { Blocks, Globe, Settings, Wand2 } from "lucide-react";
import {
openMarket,
openMask,
selectModel,
selectSupportModels,
selectWeb,
toggleWeb,
useConversationActions,
} from "@/store/chat.ts";
import { Blocks, Globe, LandPlot, Play, Settings, Wand2 } from "lucide-react";
import { useDispatch, useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import React, { useEffect, useRef } from "react";
import { openDialog } from "@/store/settings.ts";
import { cn } from "@/components/ui/lib/utils.ts";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog.tsx";
import { ScrollArea } from "@/components/ui/scroll-area.tsx";
import { getModelAvatar } from "@/components/home/ModelMarket.tsx";
import { Button } from "@/components/ui/button.tsx";
import Tips from "@/components/Tips.tsx";
import { Model } from "@/api/types.tsx";

type ChatActionProps = {
className?: string;
Expand Down Expand Up @@ -82,10 +103,76 @@ export function MarketAction() {
const { t } = useTranslation();
const dispatch = useDispatch();

const current = useSelector(selectModel);
const models = useSelector(selectSupportModels);

const [open, setOpen] = React.useState(false);

const { selected } = useConversationActions();

const event = (model: Model) => {
selected(model.id);
setOpen(false);
};

return (
<ChatAction text={t("market.title")} onClick={() => dispatch(openMarket())}>
<Blocks className={`h-4 w-4`} />
</ChatAction>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger>
<ChatAction text={t("market.title")}>
<Blocks className={`h-4 w-4`} />
</ChatAction>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{t("market.list")}</DialogTitle>
<DialogDescription>
<Button
size={`default-sm`}
className={`mt-2 w-full`}
onClick={() => dispatch(openMarket())}
>
<LandPlot className={`h-4 w-4 mr-2`} />
{t("market.go")}
</Button>
<ScrollArea
className={`flex flex-col mt-2.5 border rounded-md max-h-[60vh]`}
>
{models.map((model, index) => (
<div
key={index}
onClick={() => event(model)}
className={cn(
"flex sm:flex-row flex-col items-center px-4 py-4 sm:py-2 border-b last:border-none select-none cursor-pointer transition-all hover:bg-background-container",
model.id === current && "bg-background-container",
)}
>
<img
className={`w-6 h-6 border rounded-md`}
src={getModelAvatar(model.avatar)}
alt={""}
/>
<div className={`text-common sm:ml-2 mt-2 sm:mt-0`}>
{model.name}
</div>
<Tips className={`hidden sm:inline-block`}>{model.id}</Tips>
<Button
className={cn(
"ml-auto",
model.id === current && "text-common",
)}
size={`icon-sm`}
variant={`ghost`}
onClick={() => event(model)}
>
<Play className={`h-3.5 w-3.5`} />
</Button>
</div>
))}
</ScrollArea>
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
);
}

Expand Down
8 changes: 5 additions & 3 deletions app/src/components/home/assemblies/ChatInput.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";
import { setMemory } from "@/utils/memory.ts";
import { useTranslation } from "react-i18next";
import { Textarea } from "@/components/ui/textarea.tsx";
import { FlexibleTextarea } from "@/components/ui/textarea.tsx";
import { useSelector } from "react-redux";
import { senderSelector } from "@/store/settings.ts";
import { blobEvent } from "@/events/blob.ts";
import { cn } from "@/components/ui/lib/utils.ts";

type ChatInputProps = {
className?: string;
Expand All @@ -27,12 +28,13 @@ function ChatInput({
// sender: Ctrl + Enter if false, Enter if true

return (
<Textarea
<FlexibleTextarea
id={`input`}
className={`input-box ${className || ""}`}
className={cn("input-box no-scrollbar", className)}
ref={target}
value={value}
rows={3}
maxRows={10}
onChange={(e) => {
onValueChange(e.target.value);
setMemory("history", e.target.value);
Expand Down
1 change: 1 addition & 0 deletions app/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const buttonVariants = cva(
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
"icon-sm": "h-8 w-8",
"default-sm": "h-8 px-3",
},
},
defaultVariants: {
Expand Down
8 changes: 6 additions & 2 deletions app/src/components/ui/textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ Textarea.displayName = "Textarea";
export interface FlexibleTextareaProps extends TextareaProps {
rows?: number;
minRows?: number;
maxRows?: number;
}

const FlexibleTextarea = React.forwardRef<
HTMLTextAreaElement,
FlexibleTextareaProps
>(({ rows = 1, minRows, className, ...props }, ref) => {
>(({ rows = 1, minRows, maxRows, className, ...props }, ref) => {
const lines = useMemo(() => {
const value = props.value?.toString() || "";
const count = value.split("\n").length + 1;
return Math.max(rows, count, minRows || 1);
const res = Math.max(rows, count, minRows || 1);

if (maxRows) return Math.min(res, maxRows);
return res;
}, [props.value, rows, minRows]);

return (
Expand Down
2 changes: 1 addition & 1 deletion app/src/conf/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { syncSiteInfo } from "@/admin/api/info.ts";
import { setAxiosConfig } from "@/conf/api.ts";

export const version = "3.10.7"; // version of the current build
export const version = "3.10.8"; // version of the current build
export const dev: boolean = getDev(); // is in development mode (for debugging, in localhost origin)
export const deploy: boolean = true; // is production environment (for api endpoint)
export const tokenField = getTokenField(deploy); // token field name for storing token
Expand Down
2 changes: 2 additions & 0 deletions app/src/resources/i18n/cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@
},
"market": {
"title": "模型市场",
"list": "模型列表",
"model": "探索更多模型",
"go": "前往模型市场",
"explore": "探索",
"search": "搜索模型名称或者简介",
"model-api": "API 请求的模型 ID 名称"
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"model": "Explore more models",
"explore": "Explore",
"search": "Search model name or description",
"model-api": "Model ID name of the API request"
"model-api": "Model ID name of the API request",
"list": "Model List",
"go": "Go to the model market"
},
"conversation": {
"title": "Conversation",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"model": "他のモデルを見る",
"explore": "検索",
"search": "モデル名またはイントロダクションを検索",
"model-api": "API要求のモデルID名"
"model-api": "API要求のモデルID名",
"list": "モデルリスト",
"go": "モデルマーケットに行く"
},
"conversation": {
"title": "ダイアログ",
Expand Down
4 changes: 3 additions & 1 deletion app/src/resources/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"model": "Исследуйте больше моделей",
"explore": "Исследовать",
"search": "Поиск по имени модели или описанию",
"model-api": "Идентификатор модели запроса API"
"model-api": "Идентификатор модели запроса API",
"list": "Перечень моделей",
"go": "Перейти на модельный рынок"
},
"conversation": {
"title": "Разговор",
Expand Down
1 change: 1 addition & 0 deletions app/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ module.exports = {
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
"background-container": "hsl(var(--background-container))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
Expand Down

0 comments on commit 4b50ab2

Please sign in to comment.