From 6ea8597c6565996a46303e54a1f1fda9fa43c877 Mon Sep 17 00:00:00 2001 From: Doma Date: Fri, 6 Jan 2023 13:14:53 +0800 Subject: [PATCH] perf(deps): replace colorthief with fast-average-color --- package.json | 2 +- pnpm-lock.yaml | 104 +++----------------------------- src/hooks/useThemeColor.test.ts | 8 +-- src/hooks/useThemeColor.ts | 4 +- src/pioug__colorthief.d.ts | 9 --- src/utils/getImageColor.ts | 30 +++++---- 6 files changed, 28 insertions(+), 129 deletions(-) delete mode 100644 src/pioug__colorthief.d.ts diff --git a/package.json b/package.json index c0af3bf..421d2e5 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,8 @@ "react": "^18.2.0" }, "dependencies": { - "@pioug/colorthief": "^3.0.1", "clsx": "^1.2.1", + "fast-average-color": "^9.3.0", "use-sync-external-store": "^1.2.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7f2eb8a..11b697d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,7 +1,6 @@ lockfileVersion: 5.4 specifiers: - '@pioug/colorthief': ^3.0.1 '@testing-library/react': ^13.4.0 '@types/react': ^18.0.26 '@types/react-dom': ^18.0.9 @@ -15,6 +14,7 @@ specifiers: eslint: ^8.30.0 eslint-config-prettier: ^8.5.0 eslint-plugin-react-hooks: ^4.6.0 + fast-average-color: ^9.3.0 happy-dom: ^8.1.0 prettier: 2.5.1 react: ^18.2.0 @@ -27,8 +27,8 @@ specifiers: vitest: 0.12.6 dependencies: - '@pioug/colorthief': 3.0.1 clsx: 1.2.1 + fast-average-color: 9.3.0 use-sync-external-store: 1.2.0_react@18.2.0 devDependencies: @@ -483,31 +483,6 @@ packages: fastq: 1.11.0 dev: true - /@pioug/colorthief/3.0.1: - resolution: {integrity: sha512-b5lb5vOoeI/Rngfc2BuLx8aKQw205outUQQCrcWx4EQN2MxIAkHROChQ5Ac/raxT67Qda+8cWFoLsMx42VYSew==} - dependencies: - get-pixels: /@pioug/get-pixels/4.0.0 - quantize: /@pioug/quantize/1.2.0 - dev: false - - /@pioug/get-pixels/4.0.0: - resolution: {integrity: sha512-DALOYYWU1cqCyK4LlM8CYpVR9jYL+iPDod8plRi4FHzVOkGs40gy7ToLBKXkzcQaMAkjEvMv3JHCfirdF9ESmQ==} - dependencies: - data-uri-to-buffer: 0.0.3 - jpeg-js: 0.4.4 - mime-types: 2.1.35 - ndarray: 1.0.19 - ndarray-pack: 1.2.1 - node-bitmap: 0.0.1 - omggif: 1.0.10 - pngjs: 3.4.0 - through: 2.3.8 - dev: false - - /@pioug/quantize/1.2.0: - resolution: {integrity: sha512-T7vFO2l+ecCPYK+O9jUFWCokD1G9Kgz21Zb3Z4pOdflnud0gWjD/YnEanZvK3VanEPq5yx0OZbv7PDzX8ZvhSw==} - dev: false - /@rollup/pluginutils/5.0.2: resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} @@ -1159,16 +1134,6 @@ packages: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} dev: true - /cwise-compiler/1.1.3: - resolution: {integrity: sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==} - dependencies: - uniq: 1.0.1 - dev: false - - /data-uri-to-buffer/0.0.3: - resolution: {integrity: sha512-Cp+jOa8QJef5nXS5hU7M1DWzXPEIoVR3kbV0dQuVGwROZg8bGf1DcCnkmajBTnvghTtSNMUdRrPjgaT6ZQucbw==} - dev: false - /debug/4.3.1: resolution: {integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==} engines: {node: '>=6.0'} @@ -1878,6 +1843,11 @@ packages: strip-final-newline: 2.0.0 dev: true + /fast-average-color/9.3.0: + resolution: {integrity: sha512-FlPROSqDMOnoBgkFhWMHJODPvpS0Od0WDpedcKq4U/t0JVapGAkblNwxOr75qT+ZNd0dQM4qlgqrtnXbCJ8cNg==} + engines: {node: '>= 12'} + dev: false + /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2189,10 +2159,6 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true - /iota-array/1.0.0: - resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} - dev: false - /is-arguments/1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -2226,10 +2192,6 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-buffer/1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: false - /is-callable/1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -2354,10 +2316,6 @@ packages: engines: {node: '>=10'} dev: true - /jpeg-js/0.4.4: - resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} - dev: false - /js-sdsl/4.2.0: resolution: {integrity: sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==} dev: true @@ -2481,18 +2439,6 @@ packages: picomatch: 2.3.1 dev: true - /mime-db/1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types/2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - /mimic-fn/2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -2536,25 +2482,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /ndarray-pack/1.2.1: - resolution: {integrity: sha512-51cECUJMT0rUZNQa09EoKsnFeDL4x2dHRT0VR5U2H5ZgEcm95ZDWcMA5JShroXjHOejmAD/fg8+H+OvUnVXz2g==} - dependencies: - cwise-compiler: 1.1.3 - ndarray: 1.0.19 - dev: false - - /ndarray/1.0.19: - resolution: {integrity: sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==} - dependencies: - iota-array: 1.0.0 - is-buffer: 1.1.6 - dev: false - - /node-bitmap/0.0.1: - resolution: {integrity: sha512-Jx5lPaaLdIaOsj2mVLWMWulXF6GQVdyLvNSxmiYCvZ8Ma2hfKX0POoR2kgKOqz+oFsRreq0yYZjQ2wjE9VNzCA==} - engines: {node: '>=v0.6.5'} - dev: false - /node-fetch/2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -2620,10 +2547,6 @@ packages: object-keys: 1.1.1 dev: true - /omggif/1.0.10: - resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} - dev: false - /once/1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -2724,11 +2647,6 @@ packages: node-modules-regexp: 1.0.0 dev: true - /pngjs/3.4.0: - resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} - engines: {node: '>=4.0.0'} - dev: false - /postcss-load-config/3.0.1: resolution: {integrity: sha512-/pDHe30UYZUD11IeG8GWx9lNtu1ToyTsZHnyy45B4Mrwr/Kb6NgYl7k753+05CJNKnjbwh4975amoPJ+TEjHNQ==} engines: {node: '>= 10'} @@ -3042,10 +2960,6 @@ packages: any-promise: 1.3.0 dev: true - /through/2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false - /tinypool/0.1.3: resolution: {integrity: sha512-2IfcQh7CP46XGWGGbdyO4pjcKqsmVqFAPcXfPxcPXmOWt9cYkTP9HcDmGgsfijYoAEc4z9qcpM/BaBz46Y9/CQ==} engines: {node: '>=14.0.0'} @@ -3159,10 +3073,6 @@ packages: hasBin: true dev: true - /uniq/1.0.1: - resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==} - dev: false - /update-browserslist-db/1.0.10_browserslist@4.21.4: resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} hasBin: true diff --git a/src/hooks/useThemeColor.test.ts b/src/hooks/useThemeColor.test.ts index 7e6a63e..02e3f61 100644 --- a/src/hooks/useThemeColor.test.ts +++ b/src/hooks/useThemeColor.test.ts @@ -6,7 +6,7 @@ import { useThemeColor } from "./useThemeColor"; vi.mock("../utils/getImageColor", () => { return { - getImageColor: vi.fn(() => Promise.resolve(["r", "g", "b"])), + getImageColor: vi.fn(() => Promise.resolve("calculated")), }; }); @@ -28,7 +28,7 @@ describe("`song.theme` is not specified", () => { expect(result.current).toBe(defaultThemeColor); await waitFor(() => { - expect(result.current).toBe("rgb(r,g,b)"); + expect(result.current).toBe("calculated"); }); }); }); @@ -64,7 +64,7 @@ describe('`song.theme` is "auto"', () => { expect(result.current).toBe("green"); await waitFor(() => { - expect(result.current).toBe("rgb(r,g,b)"); + expect(result.current).toBe("calculated"); }); }); @@ -74,7 +74,7 @@ describe('`song.theme` is "auto"', () => { expect(result.current).toBe(defaultThemeColor); await waitFor(() => { - expect(result.current).toBe("rgb(r,g,b)"); + expect(result.current).toBe("calculated"); }); }); }); diff --git a/src/hooks/useThemeColor.ts b/src/hooks/useThemeColor.ts index 895d0d0..a140400 100644 --- a/src/hooks/useThemeColor.ts +++ b/src/hooks/useThemeColor.ts @@ -23,10 +23,10 @@ export function useThemeColor( if (shouldUseColorThief(song, fallback)) { const coverUrl = song!.cover!; - getImageColor(coverUrl).then(([r, g, b]) => { + getImageColor(coverUrl).then((hex) => { setCoverColorMap((prev) => ({ ...prev, - [coverUrl]: `rgb(${r},${g},${b})`, + [coverUrl]: hex, })); }); } diff --git a/src/pioug__colorthief.d.ts b/src/pioug__colorthief.d.ts deleted file mode 100644 index e8f72ba..0000000 --- a/src/pioug__colorthief.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/// - -declare module "@pioug/colorthief" { - type Color = [r: number, g: number, b: number]; - - export default class ColorThief { - getColor(sourceImage: Image, quality?: number): Color; - } -} diff --git a/src/utils/getImageColor.ts b/src/utils/getImageColor.ts index 4bfce5e..2fb0fb5 100644 --- a/src/utils/getImageColor.ts +++ b/src/utils/getImageColor.ts @@ -1,20 +1,18 @@ -import ColorThief from "@pioug/colorthief"; +import { FastAverageColor } from "fast-average-color"; -let colorThiefSingleton: ColorThief; +let facSingleton: FastAverageColor; -export function getImageColor( - imageUrl: string -): Promise<[r: number, g: number, b: number]> { - const colorThief = - colorThiefSingleton ?? (colorThiefSingleton = new ColorThief()); +/** + * @returns hex color + */ +export function getImageColor(imageUrl: string): Promise { + const fac = facSingleton ?? (facSingleton = new FastAverageColor()); - return new Promise((resolve) => { - const img = new Image(); - - img.onload = () => { - resolve(colorThief.getColor(img)); - }; - img.crossOrigin = "anonymous"; - img.src = imageUrl; - }); + return fac + .getColorAsync(imageUrl, { + ignoredColor: [255, 255, 255, 255], // Ignore white because the default background color of APlayer is white + }) + .then((color) => { + return color.hex; + }); }