Prechádzať zdrojové kódy

feat: 1)upload image with type 'heic' 2)change the empty message to ';' for models 3)

Dean-YZG 1 rok pred
rodič
commit
c10447df79
7 zmenil súbory, kde vykonal 76 pridanie a 56 odobranie
  1. 2 1
      app/components/chat.tsx
  2. 1 1
      app/store/chat.ts
  3. 6 50
      app/utils.ts
  4. 54 0
      app/utils/chat.ts
  5. 7 4
      app/utils/cloud/upstash.ts
  6. 1 0
      package.json
  7. 5 0
      yarn.lock

+ 2 - 1
app/components/chat.tsx

@@ -59,9 +59,10 @@ import {
   getMessageTextContent,
   getMessageImages,
   isVisionModel,
-  compressImage,
 } from "../utils";
 
+import { compressImage } from "@/app/utils/chat";
+
 import dynamic from "next/dynamic";
 
 import { ChatControllerPool } from "../client/controller";

+ 1 - 1
app/store/chat.ts

@@ -433,7 +433,7 @@ export const useChatStore = createPersistStore(
           content:
             session.memoryPrompt.length > 0
               ? Locale.Store.Prompt.History(session.memoryPrompt)
-              : "",
+              : ";",
           date: "",
         } as ChatMessage;
       },

+ 6 - 50
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() {
   return new Promise<string>((res, rej) => {
     const fileInput = document.createElement("input");
@@ -290,16 +248,14 @@ export function getMessageImages(message: RequestMessage): 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)
 
-  const visionKeywords = [
-    "vision",
-    "claude-3",
-    "gemini-1.5-pro",
-  ];
+  const visionKeywords = ["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
+  );
 }

+ 54 - 0
app/utils/chat.ts

@@ -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);
+  });
+}

+ 7 - 4
app/utils/cloud/upstash.ts

@@ -93,14 +93,17 @@ export function createUpstashClient(store: SyncStore) {
       }
 
       let url;
-      if (proxyUrl.length > 0 || proxyUrl === "/") {
-        let u = new URL(proxyUrl + "/api/upstash/" + path);
+      const pathPrefix = "/api/upstash/";
+
+      try {
+        let u = new URL(proxyUrl + pathPrefix + path);
         // add query params
         u.searchParams.append("endpoint", config.endpoint);
         url = u.toString();
-      } else {
-        url = "/api/upstash/" + path + "?endpoint=" + config.endpoint;
+      } catch (e) {
+        url = pathPrefix + path + "?endpoint=" + config.endpoint;
       }
+
       return url;
     },
   };

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "@vercel/speed-insights": "^1.0.2",
     "emoji-picker-react": "^4.9.2",
     "fuse.js": "^7.0.0",
+    "heic2any": "^0.0.4",
     "html-to-image": "^1.11.11",
     "mermaid": "^10.6.1",
     "nanoid": "^5.0.3",

+ 5 - 0
yarn.lock

@@ -3669,6 +3669,11 @@ heap@^0.2.6:
   resolved "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
   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:
   version "11.7.0"
   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.7.0.tgz#3ff0165bc843f8c9bce1fd89e2fda9143d24b11e"