add clean feature and fix browser compatibility in safari 17

This commit is contained in:
Zhang Minghan 2023-10-26 21:48:19 +08:00
parent 6a4d3f0ef0
commit 8f7866fe94
16 changed files with 170 additions and 140 deletions

View File

@ -11,34 +11,33 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-alert-dialog": "^1.0.4",
"@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-context-menu": "^2.1.4",
"@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-label": "^2.0.2", "@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-scroll-area": "^1.0.5",
"@radix-ui/react-select": "^2.0.0", "@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle": "^1.0.3",
"@radix-ui/react-tooltip": "^1.0.7", "@radix-ui/react-tooltip": "^1.0.6",
"@reduxjs/toolkit": "^1.9.7", "@reduxjs/toolkit": "^1.9.5",
"axios": "^1.5.1", "axios": "^1.5.0",
"chart.js": "^4.4.0", "chart.js": "^4.4.0",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"i18next": "^23.6.0", "i18next": "^23.4.6",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lucide-react": "^0.289.0", "lucide-react": "^0.289.0",
"match-sorter": "^6.3.1", "match-sorter": "^6.3.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-i18next": "^13.3.1", "react-i18next": "^13.2.2",
"react-markdown": "^8.0.7", "react-markdown": "^8.0.7",
"react-redux": "^8.1.3", "react-redux": "^8.1.2",
"react-router-dom": "^6.17.0", "react-router-dom": "^6.17.0",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"rehype-katex": "^6.0.3", "rehype-katex": "^6.0.3",
@ -50,25 +49,25 @@
"workbox-window": "^7.0.0" "workbox-window": "^7.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.8.9", "@types/node": "^20.5.9",
"@types/react": "^18.2.33", "@types/react": "^18.2.15",
"@types/react-dom": "^18.2.14", "@types/react-dom": "^18.2.7",
"@types/react-syntax-highlighter": "^15.5.9", "@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.9.0", "@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react-swc": "^3.4.0", "@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.15",
"eslint": "^8.52.0", "eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-react-refresh": "^0.4.3",
"less": "^4.2.0", "less": "^4.2.0",
"less-loader": "^11.1.3", "less-loader": "^11.1.3",
"postcss": "^8.4.31", "postcss": "^8.4.29",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.3.3",
"typescript": "^5.2.2", "typescript": "^5.0.2",
"vite": "^4.5.0", "vite": "^4.4.5",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.0",
"vite-plugin-pwa": "^0.16.5" "vite-plugin-pwa": "^0.16.4"
} }
} }

82
app/pnpm-lock.yaml generated
View File

@ -6,23 +6,20 @@ settings:
dependencies: dependencies:
'@radix-ui/react-alert-dialog': '@radix-ui/react-alert-dialog':
specifier: ^1.0.5 specifier: ^1.0.4
version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-context-menu': '@radix-ui/react-context-menu':
specifier: ^2.1.5 specifier: ^2.1.4
version: 2.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 2.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-dialog': '@radix-ui/react-dialog':
specifier: ^1.0.5 specifier: ^1.0.4
version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-dropdown-menu': '@radix-ui/react-dropdown-menu':
specifier: ^2.0.6 specifier: ^2.0.5
version: 2.0.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 2.0.6(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-label': '@radix-ui/react-label':
specifier: ^2.0.2 specifier: ^2.0.2
version: 2.0.2(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 2.0.2(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-scroll-area':
specifier: ^1.0.5
version: 1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-select': '@radix-ui/react-select':
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 2.0.0(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
@ -36,19 +33,19 @@ dependencies:
specifier: ^1.0.3 specifier: ^1.0.3
version: 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-toast': '@radix-ui/react-toast':
specifier: ^1.1.5 specifier: ^1.1.4
version: 1.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.1.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-toggle': '@radix-ui/react-toggle':
specifier: ^1.0.3 specifier: ^1.0.3
version: 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-tooltip': '@radix-ui/react-tooltip':
specifier: ^1.0.7 specifier: ^1.0.6
version: 1.0.7(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) version: 1.0.7(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@reduxjs/toolkit': '@reduxjs/toolkit':
specifier: ^1.9.7 specifier: ^1.9.5
version: 1.9.7(react-redux@8.1.3)(react@18.2.0) version: 1.9.7(react-redux@8.1.3)(react@18.2.0)
axios: axios:
specifier: ^1.5.1 specifier: ^1.5.0
version: 1.5.1 version: 1.5.1
chart.js: chart.js:
specifier: ^4.4.0 specifier: ^4.4.0
@ -60,7 +57,7 @@ dependencies:
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0 version: 2.0.0
i18next: i18next:
specifier: ^23.6.0 specifier: ^23.4.6
version: 23.6.0 version: 23.6.0
localforage: localforage:
specifier: ^1.10.0 specifier: ^1.10.0
@ -81,13 +78,13 @@ dependencies:
specifier: ^18.2.0 specifier: ^18.2.0
version: 18.2.0(react@18.2.0) version: 18.2.0(react@18.2.0)
react-i18next: react-i18next:
specifier: ^13.3.1 specifier: ^13.2.2
version: 13.3.1(i18next@23.6.0)(react-dom@18.2.0)(react@18.2.0) version: 13.3.1(i18next@23.6.0)(react-dom@18.2.0)(react@18.2.0)
react-markdown: react-markdown:
specifier: ^8.0.7 specifier: ^8.0.7
version: 8.0.7(@types/react@18.2.33)(react@18.2.0) version: 8.0.7(@types/react@18.2.33)(react@18.2.0)
react-redux: react-redux:
specifier: ^8.1.3 specifier: ^8.1.2
version: 8.1.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1) version: 8.1.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1)
react-router-dom: react-router-dom:
specifier: ^6.17.0 specifier: ^6.17.0
@ -119,31 +116,31 @@ dependencies:
devDependencies: devDependencies:
'@types/node': '@types/node':
specifier: ^20.8.9 specifier: ^20.5.9
version: 20.8.9 version: 20.8.9
'@types/react': '@types/react':
specifier: ^18.2.33 specifier: ^18.2.15
version: 18.2.33 version: 18.2.33
'@types/react-dom': '@types/react-dom':
specifier: ^18.2.14 specifier: ^18.2.7
version: 18.2.14 version: 18.2.14
'@types/react-syntax-highlighter': '@types/react-syntax-highlighter':
specifier: ^15.5.9 specifier: ^15.5.7
version: 15.5.9 version: 15.5.9
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^6.9.0 specifier: ^6.0.0
version: 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) version: 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^6.9.0 specifier: ^6.0.0
version: 6.9.0(eslint@8.52.0)(typescript@5.2.2) version: 6.9.0(eslint@8.52.0)(typescript@5.2.2)
'@vitejs/plugin-react-swc': '@vitejs/plugin-react-swc':
specifier: ^3.4.0 specifier: ^3.3.2
version: 3.4.0(vite@4.5.0) version: 3.4.0(vite@4.5.0)
autoprefixer: autoprefixer:
specifier: ^10.4.16 specifier: ^10.4.15
version: 10.4.16(postcss@8.4.31) version: 10.4.16(postcss@8.4.31)
eslint: eslint:
specifier: ^8.52.0 specifier: ^8.45.0
version: 8.52.0 version: 8.52.0
eslint-plugin-react-hooks: eslint-plugin-react-hooks:
specifier: ^4.6.0 specifier: ^4.6.0
@ -158,25 +155,25 @@ devDependencies:
specifier: ^11.1.3 specifier: ^11.1.3
version: 11.1.3(less@4.2.0)(webpack@5.89.0) version: 11.1.3(less@4.2.0)(webpack@5.89.0)
postcss: postcss:
specifier: ^8.4.31 specifier: ^8.4.29
version: 8.4.31 version: 8.4.31
prettier: prettier:
specifier: ^3.0.3 specifier: ^3.0.3
version: 3.0.3 version: 3.0.3
tailwindcss: tailwindcss:
specifier: ^3.3.5 specifier: ^3.3.3
version: 3.3.5 version: 3.3.5
typescript: typescript:
specifier: ^5.2.2 specifier: ^5.0.2
version: 5.2.2 version: 5.2.2
vite: vite:
specifier: ^4.5.0 specifier: ^4.4.5
version: 4.5.0(@types/node@20.8.9)(less@4.2.0) version: 4.5.0(@types/node@20.8.9)(less@4.2.0)
vite-plugin-html: vite-plugin-html:
specifier: ^3.2.0 specifier: ^3.2.0
version: 3.2.0(vite@4.5.0) version: 3.2.0(vite@4.5.0)
vite-plugin-pwa: vite-plugin-pwa:
specifier: ^0.16.5 specifier: ^0.16.4
version: 0.16.5(vite@4.5.0)(workbox-build@7.0.0)(workbox-window@7.0.0) version: 0.16.5(vite@4.5.0)(workbox-build@7.0.0)(workbox-window@7.0.0)
packages: packages:
@ -2171,35 +2168,6 @@ packages:
react-dom: 18.2.0(react@18.2.0) react-dom: 18.2.0(react@18.2.0)
dev: false dev: false
/@radix-ui/react-scroll-area@1.0.5(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-b6PAgH4GQf9QEn8zbT2XUHpW5z8BzqEc7Kl11TwDrvuTrxlkcjTD5qa/bxgKr+nmuXKu4L/W5UZ4mlP/VG/5Gw==}
peerDependencies:
'@types/react': '*'
'@types/react-dom': '*'
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
peerDependenciesMeta:
'@types/react':
optional: true
'@types/react-dom':
optional: true
dependencies:
'@babel/runtime': 7.23.2
'@radix-ui/number': 1.0.1
'@radix-ui/primitive': 1.0.1
'@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.33)(react@18.2.0)
'@radix-ui/react-context': 1.0.1(@types/react@18.2.33)(react@18.2.0)
'@radix-ui/react-direction': 1.0.1(@types/react@18.2.33)(react@18.2.0)
'@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0)
'@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.33)(react@18.2.0)
'@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.33)(react@18.2.0)
'@types/react': 18.2.33
'@types/react-dom': 18.2.14
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@radix-ui/react-select@2.0.0(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): /@radix-ui/react-select@2.0.0(@types/react-dom@18.2.14)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==} resolution: {integrity: sha512-RH5b7af4oHtkcHS7pG6Sgv5rk5Wxa7XI8W5gvB1N/yiuDGZxko1ynvOiVhFM7Cis2A8zxF9bTOUVbRDzPepe6w==}
peerDependencies: peerDependencies:

View File

@ -10,7 +10,7 @@ import { useEffect } from "react";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { openDialog as openQuotaDialog } from "../store/quota.ts"; import { openDialog as openQuotaDialog } from "../store/quota.ts";
import { openDialog as openSubscriptionDialog } from "../store/subscription.ts"; import { openDialog as openSubscriptionDialog } from "../store/subscription.ts";
import {AppDispatch} from "../store"; import { AppDispatch } from "../store";
type MarkdownProps = { type MarkdownProps = {
children: string; children: string;
@ -50,12 +50,17 @@ function Markdown({ children, className }: MarkdownProps) {
const url: string = href?.toString() || ""; const url: string = href?.toString() || "";
return ( return (
<a href={url} target={`_blank`} rel={`noopener noreferrer`} onClick={(e) => { <a
href={url}
target={`_blank`}
rel={`noopener noreferrer`}
onClick={(e) => {
if (doAction(dispatch, url)) e.preventDefault(); if (doAction(dispatch, url)) e.preventDefault();
}}> }}
>
{children} {children}
</a> </a>
) );
}, },
code({ inline, className, children, ...props }) { code({ inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || ""); const match = /language-(\w+)/.exec(className || "");

View File

@ -1,7 +1,22 @@
import { Button } from "./ui/button.tsx"; import { Button } from "./ui/button.tsx";
import { selectMessages } from "../store/chat.ts";
import { useDispatch, useSelector } from "react-redux";
import { MessageSquarePlus } from "lucide-react";
import { toggleConversation } from "../conversation/history.ts";
function ProjectLink() { function ProjectLink() {
return ( const dispatch = useDispatch();
const messages = useSelector(selectMessages);
return messages.length > 0 ? (
<Button
variant="outline"
size="icon"
onClick={async () => await toggleConversation(dispatch, -1)}
>
<MessageSquarePlus className={`h-4 w-4`} />
</Button>
) : (
<Button <Button
variant="outline" variant="outline"
size="icon" size="icon"

View File

@ -84,7 +84,9 @@ function SelectGroupDesktop(props: SelectGroupProps) {
</span> </span>
</SelectValue> </SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent className={`${props.className} ${props.classNameDesktop}`}> <SelectContent
className={`${props.className} ${props.classNameDesktop}`}
>
{hidden.map((select: SelectItemProps, idx: number) => ( {hidden.map((select: SelectItemProps, idx: number) => (
<SelectItem key={idx} value={select.name}> <SelectItem key={idx} value={select.name}>
<GroupSelectItem {...select} /> <GroupSelectItem {...select} />
@ -109,7 +111,11 @@ function SelectGroupMobile(props: SelectGroupProps) {
<SelectTrigger className="select-group mobile"> <SelectTrigger className="select-group mobile">
<SelectValue placeholder={props.current.value} /> <SelectValue placeholder={props.current.value} />
</SelectTrigger> </SelectTrigger>
<SelectContent position={`item-aligned`} side={props.side} className={`${props.className} ${props.classNameMobile}`}> <SelectContent
position={`item-aligned`}
side={props.side}
className={`${props.className} ${props.classNameMobile}`}
>
{props.list.map((select: SelectItemProps, idx: number) => ( {props.list.map((select: SelectItemProps, idx: number) => (
<SelectItem key={idx} value={select.name}> <SelectItem key={idx} value={select.name}>
<GroupSelectItem {...select} /> <GroupSelectItem {...select} />

View File

@ -10,7 +10,7 @@ import {
setWeb, setWeb,
} from "../../store/chat.ts"; } from "../../store/chat.ts";
import { manager } from "../../conversation/manager.ts"; import { manager } from "../../conversation/manager.ts";
import {formatMessage, triggerInstallApp} from "../../utils.ts"; import { formatMessage, triggerInstallApp } from "../../utils.ts";
import ChatInterface from "./ChatInterface.tsx"; import ChatInterface from "./ChatInterface.tsx";
import { Button } from "../ui/button.tsx"; import { Button } from "../ui/button.tsx";
import router from "../../router.tsx"; import router from "../../router.tsx";
@ -38,7 +38,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from "../ui/dialog.tsx"; } from "../ui/dialog.tsx";
import {version} from "../../conf.ts"; import { version } from "../../conf.ts";
function ChatSpace() { function ChatSpace() {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -50,10 +50,7 @@ function ChatSpace() {
{t("contact.title")} {t("contact.title")}
<ChevronRight className={`h-4 w-4 ml-2`} /> <ChevronRight className={`h-4 w-4 ml-2`} />
</Button> </Button>
<Button <Button variant={`outline`} onClick={() => router.navigate("/generate")}>
variant={`outline`}
onClick={() => router.navigate("/generate")}
>
<FolderKanban className={`h-4 w-4 mr-1.5`} /> <FolderKanban className={`h-4 w-4 mr-1.5`} />
{t("generate.title")} {t("generate.title")}
<ChevronRight className={`h-4 w-4 ml-2`} /> <ChevronRight className={`h-4 w-4 ml-2`} />
@ -68,7 +65,9 @@ function ChatSpace() {
<Button <Button
className={`mx-auto`} className={`mx-auto`}
variant={`outline`} variant={`outline`}
onClick={() => window.open("https://docs.chatnio.net", "_blank")} onClick={() =>
window.open("https://docs.chatnio.net", "_blank")
}
> >
<BookMarked className={`h-4 w-4 mr-1.5`} /> <BookMarked className={`h-4 w-4 mr-1.5`} />
{t("docs.title")} {t("docs.title")}
@ -230,12 +229,40 @@ function ChatWrapper() {
<ModelSelector side={`bottom`} /> <ModelSelector side={`bottom`} />
</div> </div>
<div className={`version`}> <div className={`version`}>
<svg className={`app`} onClick={triggerInstallApp} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor" fill="none" strokeLinecap="round" strokeLinejoin="round"> <svg
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> className={`app`}
<path d="M9 3h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z" strokeWidth="0" fill="currentColor" /> onClick={triggerInstallApp}
<path d="M9 13h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z" strokeWidth="0" fill="currentColor" /> xmlns="http://www.w3.org/2000/svg"
<path d="M19 13h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z" strokeWidth="0" fill="currentColor" /> width="24"
<path d="M17 3a1 1 0 0 1 .993 .883l.007 .117v2h2a1 1 0 0 1 .117 1.993l-.117 .007h-2v2a1 1 0 0 1 -1.993 .117l-.007 -.117v-2h-2a1 1 0 0 1 -.117 -1.993l.117 -.007h2v-2a1 1 0 0 1 1 -1z" strokeWidth="0" fill="currentColor" /> height="24"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="currentColor"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M9 3h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z"
strokeWidth="0"
fill="currentColor"
/>
<path
d="M9 13h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z"
strokeWidth="0"
fill="currentColor"
/>
<path
d="M19 13h-4a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h4a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2z"
strokeWidth="0"
fill="currentColor"
/>
<path
d="M17 3a1 1 0 0 1 .993 .883l.007 .117v2h2a1 1 0 0 1 .117 1.993l-.117 .007h-2v2a1 1 0 0 1 -1.993 .117l-.007 -.117v-2h-2a1 1 0 0 1 -.117 -1.993l.117 -.007h2v-2a1 1 0 0 1 1 -1z"
strokeWidth="0"
fill="currentColor"
/>
</svg> </svg>
chatnio v{version} chatnio v{version}
</div> </div>

View File

@ -16,8 +16,7 @@ function GetModel(name: string): Model {
type ModelSelectorProps = { type ModelSelectorProps = {
side?: "left" | "right" | "top" | "bottom"; side?: "left" | "right" | "top" | "bottom";
} };
function ModelSelector(props: ModelSelectorProps) { function ModelSelector(props: ModelSelectorProps) {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -8,9 +8,7 @@ const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger; const DialogTrigger = DialogPrimitive.Trigger;
const DialogPortal = ({ const DialogPortal = ({ ...props }: DialogPrimitive.DialogPortalProps) => (
...props
}: DialogPrimitive.DialogPortalProps) => (
<DialogPrimitive.Portal {...props} /> <DialogPrimitive.Portal {...props} />
); );
DialogPortal.displayName = DialogPrimitive.Portal.displayName; DialogPortal.displayName = DialogPrimitive.Portal.displayName;

View File

@ -1,7 +1,7 @@
import * as React from "react" import * as React from "react";
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
import { cn } from "./lib/utils" import { cn } from "./lib/utils";
const ScrollArea = React.forwardRef< const ScrollArea = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.Root>, React.ElementRef<typeof ScrollAreaPrimitive.Root>,
@ -18,8 +18,8 @@ const ScrollArea = React.forwardRef<
<ScrollBar /> <ScrollBar />
<ScrollAreaPrimitive.Corner /> <ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root> </ScrollAreaPrimitive.Root>
)) ));
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
const ScrollBar = React.forwardRef< const ScrollBar = React.forwardRef<
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>, React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
@ -34,18 +34,18 @@ const ScrollBar = React.forwardRef<
"h-full w-2.5 border-l border-l-transparent p-[1px]", "h-full w-2.5 border-l border-l-transparent p-[1px]",
orientation === "horizontal" && orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent p-[1px]", "h-2.5 flex-col border-t border-t-transparent p-[1px]",
className className,
)} )}
{...props} {...props}
> >
<ScrollAreaPrimitive.ScrollAreaThumb <ScrollAreaPrimitive.ScrollAreaThumb
className={cn( className={cn(
"relative rounded-full bg-border", "relative rounded-full bg-border",
orientation === "vertical" && "flex-1" orientation === "vertical" && "flex-1",
)} )}
/> />
</ScrollAreaPrimitive.ScrollAreaScrollbar> </ScrollAreaPrimitive.ScrollAreaScrollbar>
)) ));
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
export { ScrollArea, ScrollBar } export { ScrollArea, ScrollBar };

View File

@ -38,23 +38,25 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content <SelectPrimitive.Content
avoidCollisions={true} avoidCollisions={true}
ref={(ref) => { ref={(ref) => {
if (!ref) return if (!ref) return;
ref.ontouchend = (e) => { ref.ontouchend = (e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} };
}} }}
className={cn( className={cn(
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" ? position === "popper"
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1": ? "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1"
"w-[80vw] max-w-[30rem] max-h-[80vh]", : "w-[80vw] max-w-[30rem] max-h-[80vh]",
className, className,
)} )}
position={position} position={position}
{...props} {...props}
> >
<SelectPrimitive.ScrollUpButton className={`flex items-center justify-center h-[25px] cursor-pointer`}> <SelectPrimitive.ScrollUpButton
className={`flex items-center justify-center h-[25px] cursor-pointer`}
>
<ChevronUp /> <ChevronUp />
</SelectPrimitive.ScrollUpButton> </SelectPrimitive.ScrollUpButton>
<SelectPrimitive.Viewport <SelectPrimitive.Viewport
@ -66,7 +68,9 @@ const SelectContent = React.forwardRef<
> >
{children} {children}
</SelectPrimitive.Viewport> </SelectPrimitive.Viewport>
<SelectPrimitive.ScrollDownButton className={`flex items-center justify-center h-[25px] cursor-pointer`}> <SelectPrimitive.ScrollDownButton
className={`flex items-center justify-center h-[25px] cursor-pointer`}
>
<ChevronDown /> <ChevronDown />
</SelectPrimitive.ScrollDownButton> </SelectPrimitive.ScrollDownButton>
</SelectPrimitive.Content> </SelectPrimitive.Content>

View File

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
import { Model } from "./conversation/types.ts"; import { Model } from "./conversation/types.ts";
export const version = "3.5.16"; export const version = "3.5.17";
export const dev: boolean = window.location.hostname === "localhost"; export const dev: boolean = window.location.hostname === "localhost";
export const deploy: boolean = true; export const deploy: boolean = true;
export let rest_api: string = "http://localhost:8094"; export let rest_api: string = "http://localhost:8094";

View File

@ -18,7 +18,7 @@ type SubscriptionResponse = {
usage: { usage: {
gpt4: number; gpt4: number;
dalle: number; dalle: number;
} };
}; };
type BuySubscriptionResponse = { type BuySubscriptionResponse = {
@ -62,12 +62,22 @@ export async function getSubscription(): Promise<SubscriptionResponse> {
try { try {
const resp = await axios.get(`/subscription`); const resp = await axios.get(`/subscription`);
if (resp.data.status === false) { if (resp.data.status === false) {
return { status: false, is_subscribed: false, expired: 0, usage: { gpt4: 0, dalle: 0 } }; return {
status: false,
is_subscribed: false,
expired: 0,
usage: { gpt4: 0, dalle: 0 },
};
} }
return resp.data as SubscriptionResponse; return resp.data as SubscriptionResponse;
} catch (e) { } catch (e) {
console.debug(e); console.debug(e);
return { status: false, is_subscribed: false, expired: 0 , usage: { gpt4: 0, dalle: 0 } }; return {
status: false,
is_subscribed: false,
expired: 0,
usage: { gpt4: 0, dalle: 0 },
};
} }
} }

View File

@ -4,7 +4,8 @@ import {
isSubscribedSelector, isSubscribedSelector,
refreshSubscription, refreshSubscription,
refreshSubscriptionTask, refreshSubscriptionTask,
setDialog, usageSelector, setDialog,
usageSelector,
} from "../store/subscription.ts"; } from "../store/subscription.ts";
import { import {
Dialog, Dialog,
@ -185,7 +186,7 @@ function Subscription() {
GPT-4 GPT-4
<div className={`grow`} /> <div className={`grow`} />
<div className={`sub-value`}> <div className={`sub-value`}>
<p>{ usage?.gpt4 }</p> / <p> 50 </p> <p>{usage?.gpt4}</p> / <p> 50 </p>
</div> </div>
</div> </div>
<div className={`sub-column`}> <div className={`sub-column`}>
@ -193,7 +194,7 @@ function Subscription() {
DALL-E DALL-E
<div className={`grow`} /> <div className={`grow`} />
<div className={`sub-value`}> <div className={`sub-value`}>
<p>{ usage?.dalle }</p> / <p> 2000 </p> <p>{usage?.dalle}</p> / <p> 2000 </p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -11,7 +11,7 @@ export const subscriptionSlice = createSlice({
usage: { usage: {
gpt4: 0, gpt4: 0,
dalle: 0, dalle: 0,
} },
}, },
reducers: { reducers: {
toggleDialog: (state) => { toggleDialog: (state) => {
@ -49,8 +49,7 @@ export const isSubscribedSelector = (state: any): boolean =>
state.subscription.is_subscribed; state.subscription.is_subscribed;
export const expiredSelector = (state: any): number => export const expiredSelector = (state: any): number =>
state.subscription.expired; state.subscription.expired;
export const usageSelector = (state: any): any => export const usageSelector = (state: any): any => state.subscription.usage;
state.subscription.usage;
export const refreshSubscription = async (dispatch: AppDispatch) => { export const refreshSubscription = async (dispatch: AppDispatch) => {
const current = new Date().getTime(); //@ts-ignore const current = new Date().getTime(); //@ts-ignore

View File

@ -1 +1 @@
declare module '@radix-ui/react-select-area'; declare module "@radix-ui/react-select-area";

View File

@ -8,10 +8,9 @@ window.addEventListener("resize", () => {
mobile = isMobile(); mobile = isMobile();
}); });
window.addEventListener("beforeinstallprompt", (e: Event) => {
window.addEventListener('beforeinstallprompt', (e: Event) => {
// e.preventDefault(); // e.preventDefault();
event = (e as BeforeInstallPromptEvent); event = e as BeforeInstallPromptEvent;
}); });
export function triggerInstallApp() { export function triggerInstallApp() {