feat: 1)upload image with type 'heic' 2)change the empty message to ';' for models 3)
This commit is contained in:
parent
3513c6801e
commit
c10447df79
|
@ -59,9 +59,10 @@ import {
|
||||||
getMessageTextContent,
|
getMessageTextContent,
|
||||||
getMessageImages,
|
getMessageImages,
|
||||||
isVisionModel,
|
isVisionModel,
|
||||||
compressImage,
|
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
|
import { compressImage } from "@/app/utils/chat";
|
||||||
|
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
import { ChatControllerPool } from "../client/controller";
|
import { ChatControllerPool } from "../client/controller";
|
||||||
|
|
|
@ -433,7 +433,7 @@ export const useChatStore = createPersistStore(
|
||||||
content:
|
content:
|
||||||
session.memoryPrompt.length > 0
|
session.memoryPrompt.length > 0
|
||||||
? Locale.Store.Prompt.History(session.memoryPrompt)
|
? Locale.Store.Prompt.History(session.memoryPrompt)
|
||||||
: "",
|
: ";",
|
||||||
date: "",
|
date: "",
|
||||||
} as ChatMessage;
|
} as ChatMessage;
|
||||||
},
|
},
|
||||||
|
|
56
app/utils.ts
56
app/utils.ts
|
@ -83,48 +83,6 @@ export async function downloadAs(text: string, filename: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compressImage(file: File, maxSize: number): Promise<string> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (readerEvent: any) => {
|
|
||||||
const image = new Image();
|
|
||||||
image.onload = () => {
|
|
||||||
let canvas = document.createElement("canvas");
|
|
||||||
let ctx = canvas.getContext("2d");
|
|
||||||
let width = image.width;
|
|
||||||
let height = image.height;
|
|
||||||
let quality = 0.9;
|
|
||||||
let dataUrl;
|
|
||||||
|
|
||||||
do {
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
ctx?.drawImage(image, 0, 0, width, height);
|
|
||||||
dataUrl = canvas.toDataURL("image/jpeg", quality);
|
|
||||||
|
|
||||||
if (dataUrl.length < maxSize) break;
|
|
||||||
|
|
||||||
if (quality > 0.5) {
|
|
||||||
// Prioritize quality reduction
|
|
||||||
quality -= 0.1;
|
|
||||||
} else {
|
|
||||||
// Then reduce the size
|
|
||||||
width *= 0.9;
|
|
||||||
height *= 0.9;
|
|
||||||
}
|
|
||||||
} while (dataUrl.length > maxSize);
|
|
||||||
|
|
||||||
resolve(dataUrl);
|
|
||||||
};
|
|
||||||
image.onerror = reject;
|
|
||||||
image.src = readerEvent.target.result;
|
|
||||||
};
|
|
||||||
reader.onerror = reject;
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readFromFile() {
|
export function readFromFile() {
|
||||||
return new Promise<string>((res, rej) => {
|
return new Promise<string>((res, rej) => {
|
||||||
const fileInput = document.createElement("input");
|
const fileInput = document.createElement("input");
|
||||||
|
@ -290,16 +248,14 @@ export function getMessageImages(message: RequestMessage): string[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isVisionModel(model: string) {
|
export function isVisionModel(model: string) {
|
||||||
|
|
||||||
// Note: This is a better way using the TypeScript feature instead of `&&` or `||` (ts v5.5.0-dev.20240314 I've been using)
|
// Note: This is a better way using the TypeScript feature instead of `&&` or `||` (ts v5.5.0-dev.20240314 I've been using)
|
||||||
|
|
||||||
const visionKeywords = [
|
const visionKeywords = ["vision", "claude-3", "gemini-1.5-pro"];
|
||||||
"vision",
|
|
||||||
"claude-3",
|
|
||||||
"gemini-1.5-pro",
|
|
||||||
];
|
|
||||||
|
|
||||||
const isGpt4Turbo = model.includes("gpt-4-turbo") && !model.includes("preview");
|
const isGpt4Turbo =
|
||||||
|
model.includes("gpt-4-turbo") && !model.includes("preview");
|
||||||
|
|
||||||
return visionKeywords.some((keyword) => model.includes(keyword)) || isGpt4Turbo;
|
return (
|
||||||
|
visionKeywords.some((keyword) => model.includes(keyword)) || isGpt4Turbo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import heic2any from "heic2any";
|
||||||
|
|
||||||
|
export function compressImage(file: File, maxSize: number): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (readerEvent: any) => {
|
||||||
|
const image = new Image();
|
||||||
|
image.onload = () => {
|
||||||
|
let canvas = document.createElement("canvas");
|
||||||
|
let ctx = canvas.getContext("2d");
|
||||||
|
let width = image.width;
|
||||||
|
let height = image.height;
|
||||||
|
let quality = 0.9;
|
||||||
|
let dataUrl;
|
||||||
|
|
||||||
|
do {
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx?.drawImage(image, 0, 0, width, height);
|
||||||
|
dataUrl = canvas.toDataURL("image/jpeg", quality);
|
||||||
|
|
||||||
|
if (dataUrl.length < maxSize) break;
|
||||||
|
|
||||||
|
if (quality > 0.5) {
|
||||||
|
// Prioritize quality reduction
|
||||||
|
quality -= 0.1;
|
||||||
|
} else {
|
||||||
|
// Then reduce the size
|
||||||
|
width *= 0.9;
|
||||||
|
height *= 0.9;
|
||||||
|
}
|
||||||
|
} while (dataUrl.length > maxSize);
|
||||||
|
|
||||||
|
resolve(dataUrl);
|
||||||
|
};
|
||||||
|
image.onerror = reject;
|
||||||
|
image.src = readerEvent.target.result;
|
||||||
|
};
|
||||||
|
reader.onerror = reject;
|
||||||
|
|
||||||
|
if (file.type.includes("heic")) {
|
||||||
|
heic2any({ blob: file, toType: "image/jpeg" })
|
||||||
|
.then((blob) => {
|
||||||
|
reader.readAsDataURL(blob as Blob);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
reject(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
});
|
||||||
|
}
|
|
@ -93,14 +93,17 @@ export function createUpstashClient(store: SyncStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let url;
|
let url;
|
||||||
if (proxyUrl.length > 0 || proxyUrl === "/") {
|
const pathPrefix = "/api/upstash/";
|
||||||
let u = new URL(proxyUrl + "/api/upstash/" + path);
|
|
||||||
|
try {
|
||||||
|
let u = new URL(proxyUrl + pathPrefix + path);
|
||||||
// add query params
|
// add query params
|
||||||
u.searchParams.append("endpoint", config.endpoint);
|
u.searchParams.append("endpoint", config.endpoint);
|
||||||
url = u.toString();
|
url = u.toString();
|
||||||
} else {
|
} catch (e) {
|
||||||
url = "/api/upstash/" + path + "?endpoint=" + config.endpoint;
|
url = pathPrefix + path + "?endpoint=" + config.endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"@vercel/speed-insights": "^1.0.2",
|
"@vercel/speed-insights": "^1.0.2",
|
||||||
"emoji-picker-react": "^4.9.2",
|
"emoji-picker-react": "^4.9.2",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
|
"heic2any": "^0.0.4",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"mermaid": "^10.6.1",
|
"mermaid": "^10.6.1",
|
||||||
"nanoid": "^5.0.3",
|
"nanoid": "^5.0.3",
|
||||||
|
|
|
@ -3669,6 +3669,11 @@ heap@^0.2.6:
|
||||||
resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
|
resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
|
||||||
integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==
|
integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==
|
||||||
|
|
||||||
|
heic2any@^0.0.4:
|
||||||
|
version "0.0.4"
|
||||||
|
resolved "https://registry.npmmirror.com/heic2any/-/heic2any-0.0.4.tgz#eddb8e6fec53c8583a6e18b65069bb5e8d19028a"
|
||||||
|
integrity sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA==
|
||||||
|
|
||||||
highlight.js@~11.7.0:
|
highlight.js@~11.7.0:
|
||||||
version "11.7.0"
|
version "11.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e"
|
||||||
|
|
Loading…
Reference in New Issue