mirror of
https://github.com/coaidev/coai.git
synced 2025-05-20 05:20:15 +09:00
feat: refresh api key feature and image file preview feature
This commit is contained in:
parent
e5755a000d
commit
b6049e28ff
@ -32,5 +32,6 @@ func AnalysisRequest(model string, buffer *utils.Buffer, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
IncrRequest(instance)
|
||||
IncrModelRequest(instance, model, int64(buffer.CountToken()))
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "chatnio",
|
||||
"version": "3.8.0"
|
||||
"version": "3.8.1"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
|
@ -5,8 +5,7 @@
|
||||
.file-instance {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin: 2px 0 !important;
|
||||
margin-bottom: 4px !important;
|
||||
padding: 6px 12px !important;
|
||||
@ -14,6 +13,22 @@
|
||||
background: hsla(var(--background-container)) !important;
|
||||
border-radius: var(--radius);
|
||||
|
||||
.file-content {
|
||||
background: none !important;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 320px;
|
||||
max-height: 240px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius);
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
@media (max-width: 668px) {
|
||||
& {
|
||||
white-space: pre-wrap;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { File } from "lucide-react";
|
||||
import { saveAsFile } from "@/utils/dom.ts";
|
||||
import { useMemo } from "react";
|
||||
|
||||
/**
|
||||
* file format:
|
||||
@ -12,6 +13,13 @@ import { saveAsFile } from "@/utils/dom.ts";
|
||||
export function parseFile(data: string) {
|
||||
const filename = data.split("\n")[0].replace("[[", "").replace("]]", "");
|
||||
const content = data.replace(`[[${filename}]]\n`, "");
|
||||
const image = useMemo(() => {
|
||||
// get image url from content (like: https://i.imgur.com/xxxxx.png)
|
||||
const match = content
|
||||
.toLowerCase()
|
||||
.match(/(https?:\/\/.*\.(?:png|jpg|jpeg|gif))/);
|
||||
return match ? match[0] : "";
|
||||
}, [filename, content]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -23,8 +31,11 @@ export function parseFile(data: string) {
|
||||
saveAsFile(filename, content);
|
||||
}}
|
||||
>
|
||||
<File className={`mr-1`} />
|
||||
<span className={`name`}>{filename}</span>
|
||||
<div className={`file-content`}>
|
||||
<File className={`mr-1`} />
|
||||
<span className={`name`}>{filename}</span>
|
||||
</div>
|
||||
{image && <img src={image} className={`file-image`} alt={""} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import React from "react";
|
||||
import { syncSiteInfo } from "@/admin/api/info.ts";
|
||||
import { loadPreferenceModels } from "@/utils/storage.ts";
|
||||
|
||||
export const version = "3.8.0-rc";
|
||||
export const version = "3.8.1";
|
||||
export const dev: boolean = getDev();
|
||||
export const deploy: boolean = true;
|
||||
export let rest_api: string = getRestApi(deploy);
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
getApiKey,
|
||||
} from "@/store/api.ts";
|
||||
import { Input } from "@/components/ui/input.tsx";
|
||||
import { Copy, ExternalLink } from "lucide-react";
|
||||
import { Copy, ExternalLink, RotateCw } from "lucide-react";
|
||||
import { useToast } from "@/components/ui/use-toast.ts";
|
||||
import { copyClipboard } from "@/utils/dom.ts";
|
||||
import { useEffectAsync } from "@/utils/hook.ts";
|
||||
@ -53,6 +53,13 @@ function ApikeyDialog() {
|
||||
<DialogDescription asChild>
|
||||
<div className={`api-dialog`}>
|
||||
<div className={`api-wrapper`}>
|
||||
<Button
|
||||
variant={`outline`}
|
||||
size={`icon`}
|
||||
onClick={() => getApiKey(dispatch)}
|
||||
>
|
||||
<RotateCw className={`h-4 w-4`} />
|
||||
</Button>
|
||||
<Input value={key} />
|
||||
<Button variant={`default`} size={`icon`} onClick={copyKey}>
|
||||
<Copy className={`h-4 w-4`} />
|
||||
|
@ -8,7 +8,9 @@ export async function copyClipboard(text: string) {
|
||||
*/
|
||||
|
||||
try {
|
||||
if (navigator.clipboard) return await navigator.clipboard.writeText(text);
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return await navigator.clipboard.writeText(text);
|
||||
}
|
||||
|
||||
const el = document.createElement("textarea");
|
||||
el.value = text;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"chat/admin"
|
||||
"chat/utils"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -62,7 +61,6 @@ func ThrottleMiddleware() gin.HandlerFunc {
|
||||
ip := c.ClientIP()
|
||||
path := c.Request.URL.Path
|
||||
cache := utils.GetCacheFromContext(c)
|
||||
admin.IncrRequest(cache)
|
||||
|
||||
limiter := GetPrefixMap[Limiter](path, limits)
|
||||
if limiter != nil && limiter.RateLimit(cache, ip, path) {
|
||||
|
@ -58,5 +58,11 @@ func RegisterStaticRoute(engine *gin.Engine) {
|
||||
c.File("./app/dist/index.html")
|
||||
})
|
||||
|
||||
// redirect /v1 to /api/v1
|
||||
engine.Any("/v1/*path", func(c *gin.Context) {
|
||||
path := c.Param("path")
|
||||
c.Redirect(301, fmt.Sprintf("/api/v1/%s", path))
|
||||
})
|
||||
|
||||
fmt.Println(`[service] start serving static files from ~/app/dist`)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user