From 3e01da6a9ed5365068860d60ef79acacfa4d9169 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Fri, 11 Oct 2024 15:38:08 +0900 Subject: [PATCH 1/5] update biome --- biome.json | 2 +- package.json | 6 +--- pnpm-lock.yaml | 97 ++++++++++++++++++++++++-------------------------- 3 files changed, 49 insertions(+), 56 deletions(-) diff --git a/biome.json b/biome.json index 9926b2f..20573f3 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.6.3/schema.json", + "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", "organizeImports": { "enabled": true }, diff --git a/package.json b/package.json index 5f3b533..b31d65f 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "virtua": "^0.35.0" }, "devDependencies": { - "@biomejs/biome": "^1.6.3", + "@biomejs/biome": "^1.9.3", "@pandacss/dev": "^0.37.2", "@shadow-panda/preset": "^0.7.1", "@types/node": "^20.12.5", @@ -61,12 +61,8 @@ "date-fns": "^3.2.0", "i18next-parser": "^8.12.0", "npm-run-all2": "^6.1.2", - "prettier": "^3.2.5", "tsx": "^4.7.1", "typescript": "^5.6.3", "vite": "^5.2.14" - }, - "prettier": { - "printWidth": 120 } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 90acc95..8b6c322 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,8 +76,8 @@ importers: version: 0.35.0(react-dom@18.2.0(react@18.3.1))(react@18.3.1) devDependencies: '@biomejs/biome': - specifier: ^1.6.3 - version: 1.6.3 + specifier: ^1.9.3 + version: 1.9.3 '@pandacss/dev': specifier: ^0.37.2 version: 0.37.2(typescript@5.6.3) @@ -105,9 +105,6 @@ importers: npm-run-all2: specifier: ^6.1.2 version: 6.1.2 - prettier: - specifier: ^3.2.5 - version: 3.2.5 tsx: specifier: ^4.7.1 version: 4.7.1 @@ -235,56 +232,56 @@ packages: resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} engines: {node: '>=6.9.0'} - '@biomejs/biome@1.6.3': - resolution: {integrity: sha512-Xnp/TIpIcTnRA4LwerJuoGYQJEqwXtn5AL0U0OPXll/QGbAKmcUAfizU880xTwZRD4f53iceqODLDaD3wxYlIw==} - engines: {node: '>=14.*'} + '@biomejs/biome@1.9.3': + resolution: {integrity: sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ==} + engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@1.6.3': - resolution: {integrity: sha512-0E8PGu3/8HSkBJdtjno+niJE1ANS/12D7sPK65vw5lTBYmmaYwJdfclDp6XO0IAX7uVd3/YtXlsEua0SVrNt3Q==} - engines: {node: '>=14.*'} + '@biomejs/cli-darwin-arm64@1.9.3': + resolution: {integrity: sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ==} + engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@1.6.3': - resolution: {integrity: sha512-UWu0We/aIRtWXgJKe6ygWt2xR0yXs64BwWqtZbfxBojRn3jgW8UdFAkV5yiUOX3TQlsV6BZH1EQaUAVsccUeeA==} - engines: {node: '>=14.*'} + '@biomejs/cli-darwin-x64@1.9.3': + resolution: {integrity: sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw==} + engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@1.6.3': - resolution: {integrity: sha512-AntGCSfLN1nPcQj4VOk3X2JgnDw07DaPC8BuBmRcsRmn+7GPSWLllVN5awIKlRPZEbGJtSnLkTiDc5Bxw8OiuA==} - engines: {node: '>=14.*'} + '@biomejs/cli-linux-arm64-musl@1.9.3': + resolution: {integrity: sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q==} + engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@1.6.3': - resolution: {integrity: sha512-wFVkQw38kOssfnkbpSh6ums5TaElw3RAt5i/VZwHmgR2nQgE0fHXLO7HwIE9VBkOEdbiIFq+2PxvFIHuJF3z3Q==} - engines: {node: '>=14.*'} + '@biomejs/cli-linux-arm64@1.9.3': + resolution: {integrity: sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ==} + engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@1.6.3': - resolution: {integrity: sha512-GelAvGsUwbxfFpKLG+7+dvDmbrfkGqn08sL8CMQrGnhjE1krAqHWiXQsjfmi0UMFdMsk7hbc4oSAP+1+mrXcHQ==} - engines: {node: '>=14.*'} + '@biomejs/cli-linux-x64-musl@1.9.3': + resolution: {integrity: sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA==} + engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@1.6.3': - resolution: {integrity: sha512-vyn8TQaTZg617hjqFitwGmb1St5XXvq6I3vmxU/QFalM74BryMSvYCrYWb2Yw/TkykdEwZTMGYp+SWHRb04fTg==} - engines: {node: '>=14.*'} + '@biomejs/cli-linux-x64@1.9.3': + resolution: {integrity: sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA==} + engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@1.6.3': - resolution: {integrity: sha512-Gx8N2Tixke6pAI1BniteCVZgUUmaFEDYosdWxoaCus15BZI/7RcBxhsRM0ZL/lC66StSQ8vHl8JBrrld1k570Q==} - engines: {node: '>=14.*'} + '@biomejs/cli-win32-arm64@1.9.3': + resolution: {integrity: sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw==} + engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@1.6.3': - resolution: {integrity: sha512-meungPJw64SqoR7LXY1wG7GC4+4wgpyThdFUMGXa6PCe0BLFOIOcZ9VMj9PstuczMPdgmt/BUMPsj25dK1VO8A==} - engines: {node: '>=14.*'} + '@biomejs/cli-win32-x64@1.9.3': + resolution: {integrity: sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q==} + engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -2816,39 +2813,39 @@ snapshots: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - '@biomejs/biome@1.6.3': + '@biomejs/biome@1.9.3': optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.6.3 - '@biomejs/cli-darwin-x64': 1.6.3 - '@biomejs/cli-linux-arm64': 1.6.3 - '@biomejs/cli-linux-arm64-musl': 1.6.3 - '@biomejs/cli-linux-x64': 1.6.3 - '@biomejs/cli-linux-x64-musl': 1.6.3 - '@biomejs/cli-win32-arm64': 1.6.3 - '@biomejs/cli-win32-x64': 1.6.3 - - '@biomejs/cli-darwin-arm64@1.6.3': + '@biomejs/cli-darwin-arm64': 1.9.3 + '@biomejs/cli-darwin-x64': 1.9.3 + '@biomejs/cli-linux-arm64': 1.9.3 + '@biomejs/cli-linux-arm64-musl': 1.9.3 + '@biomejs/cli-linux-x64': 1.9.3 + '@biomejs/cli-linux-x64-musl': 1.9.3 + '@biomejs/cli-win32-arm64': 1.9.3 + '@biomejs/cli-win32-x64': 1.9.3 + + '@biomejs/cli-darwin-arm64@1.9.3': optional: true - '@biomejs/cli-darwin-x64@1.6.3': + '@biomejs/cli-darwin-x64@1.9.3': optional: true - '@biomejs/cli-linux-arm64-musl@1.6.3': + '@biomejs/cli-linux-arm64-musl@1.9.3': optional: true - '@biomejs/cli-linux-arm64@1.6.3': + '@biomejs/cli-linux-arm64@1.9.3': optional: true - '@biomejs/cli-linux-x64-musl@1.6.3': + '@biomejs/cli-linux-x64-musl@1.9.3': optional: true - '@biomejs/cli-linux-x64@1.6.3': + '@biomejs/cli-linux-x64@1.9.3': optional: true - '@biomejs/cli-win32-arm64@1.6.3': + '@biomejs/cli-win32-arm64@1.9.3': optional: true - '@biomejs/cli-win32-x64@1.6.3': + '@biomejs/cli-win32-x64@1.9.3': optional: true '@clack/core@0.3.4': From 722b911ca1e43f67755dd00633577dc4bc7e18da Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Fri, 11 Oct 2024 15:44:00 +0900 Subject: [PATCH 2/5] migrate songdata api --- src/components/ShareMusicDialog.tsx | 81 +++++++++++++++++++---------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/src/components/ShareMusicDialog.tsx b/src/components/ShareMusicDialog.tsx index 4634a7e..5852b24 100644 --- a/src/components/ShareMusicDialog.tsx +++ b/src/components/ShareMusicDialog.tsx @@ -1,9 +1,11 @@ import { css } from "@shadow-panda/styled-system/css"; import { divider, hstack } from "@shadow-panda/styled-system/patterns"; import { t } from "i18next"; -import { atom, useAtomValue, useSetAtom } from "jotai"; +import { atom, useAtomValue } from "jotai"; import { loadable } from "jotai/utils"; import { useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import type { LangCode } from "../locales/i18n"; import { myMusicStatusAtom, updateMyStatus } from "../states/nostr"; import { button } from "../styles/recipes"; import { useCloseHeaderMenu } from "./HeaderMenu"; @@ -12,33 +14,54 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogT import { Input } from "./ui/input"; import { Label } from "./ui/label"; -type MusicData = { +type SongData = { url: string; title?: string; - artists?: string[]; + artist?: string; }; -const songwhipProxyUrl = "https://songwhip-proxy.c-stellar.net/"; +const songDataApiUrl = "https://nostatus-songdata-api.c-stellar.net/"; -const fetchMusicData = async (musicLink: string): Promise => { - const resp = await fetch(`${songwhipProxyUrl}?url=${encodeURIComponent(musicLink)}`); +const langCodeToCountry = (lang: LangCode) => { + switch (lang) { + case "ja": + return "JP"; + case "en": + return "US"; + default: + return "US"; + } +}; + +const fetchSongData = async (musicLink: string, lang: LangCode): Promise => { + const apiUrl = new URL(songDataApiUrl); + + const params = new URLSearchParams(); + params.set("url", musicLink); + params.set("country", langCodeToCountry(lang)); + apiUrl.search = params.toString(); + + const resp = await fetch(apiUrl); if (!resp.ok) { - throw Error("failed to fetch music data"); + throw Error("failed to fetch song data"); } - return resp.json() as Promise; + return resp.json() as Promise; }; -const musicLinkAtom = atom(undefined); +const makeMusicDataLoadableAtom = (musicLink: string | undefined, lang: LangCode) => + loadable( + atom(async () => { + if (musicLink === undefined) { + return Promise.resolve(undefined); + } + return fetchSongData(musicLink, lang); + }), + ); -const musicDataLoadableAtom = loadable( - atom(async (get) => { - const musicLink = get(musicLinkAtom); - if (musicLink === undefined) { - return Promise.resolve(undefined); - } - return fetchMusicData(musicLink); - }), -); +const useSongDataLoadable = (musicLink: string | undefined, lang: LangCode) => { + const songDataLoadableAtom = useMemo(() => makeMusicDataLoadableAtom(musicLink, lang), [musicLink, lang]); + return useAtomValue(songDataLoadableAtom); +}; type ShareMusicDialogProps = { trigger: React.ReactNode; @@ -50,18 +73,20 @@ export const ShareMusicDialog: React.FC = ({ trigger }) = const [open, setOpen] = useState(false); const closeHeaderMenu = useCloseHeaderMenu(); + const { i18n } = useTranslation(); const [musicLinkInput, setMusicLinkInput] = useState(""); - const setMusicLink = useSetAtom(musicLinkAtom); - const musicData = useAtomValue(musicDataLoadableAtom); + const [musicLink, setMusicLink] = useState(undefined); + + const songData = useSongDataLoadable(musicLink, i18n.language as LangCode); const newMusicStatus = useMemo(() => { - if (musicData.state !== "hasData" || musicData.data === undefined) { + if (songData.state !== "hasData" || songData.data === undefined) { return undefined; } return { - content: `${musicData.data.title || "???"} - ${(musicData.data.artists ?? []).join(", ")}`, - linkUrl: musicData.data.url, + content: `${songData.data.title || "???"} - ${songData.data.artist || "???"}`, + linkUrl: songData.data.url, }; - }, [musicData]); + }, [songData]); const currMusicStatus = useAtomValue(myMusicStatusAtom); @@ -124,20 +149,20 @@ export const ShareMusicDialog: React.FC = ({ trigger }) = - {(musicData.state !== "hasData" || newMusicStatus !== undefined) && ( + {(songData.state !== "hasData" || newMusicStatus !== undefined) && (

{t("musicStatusPreview")}

)} - {musicData.state === "loading" &&

{t("musicDataLoading")}

} + {songData.state === "loading" &&

{t("musicDataLoading")}

} {newMusicStatus !== undefined && } - {musicData.state === "hasError" && ( + {songData.state === "hasError" && (

{t("fetchingMusicDataFailed")}

)} From 1a14e4e659fc195220f8642cba0811c3f2d230c7 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Fri, 11 Oct 2024 15:52:04 +0900 Subject: [PATCH 3/5] pass song data API URL as env var --- .env.development | 1 + .env.production | 1 + .gitignore | 1 + scripts/genBuildId.ts | 6 +++--- src/components/ShareMusicDialog.tsx | 4 +--- src/env.d.ts | 9 --------- src/vite-env.d.ts | 9 +++++++++ 7 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 .env.development create mode 100644 .env.production delete mode 100644 src/env.d.ts diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..cc95231 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VITE_SONGDATA_API_URL=http://localhost:8787/ \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f3110e7 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +VITE_SONGDATA_API_URL=https://nostatus-songdata-api.c-stellar.net/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9ece64e..09dd713 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ dev-dist *.local .env +.env*.local # Editor directories and files .vscode/* diff --git a/scripts/genBuildId.ts b/scripts/genBuildId.ts index 3290b5b..208575f 100644 --- a/scripts/genBuildId.ts +++ b/scripts/genBuildId.ts @@ -1,6 +1,6 @@ -import cp from "child_process"; import { format } from "date-fns"; -import { writeFileSync } from "fs"; +import cp from "node:child_process"; +import { writeFileSync } from "node:fs"; process.env.TZ = "Asia/Tokyo"; const timestamp = format(new Date(), "yyyyMMddHHmm"); @@ -9,4 +9,4 @@ const commitHash = cp.execSync("git rev-parse --short=7 HEAD", { encoding: "utf8 const buildId = `${timestamp}-${commitHash}`; console.log("Build ID:", buildId); -writeFileSync(".env", `VITE_BUILD_ID=${buildId}`); +writeFileSync(".env.local", `VITE_BUILD_ID=${buildId}`); diff --git a/src/components/ShareMusicDialog.tsx b/src/components/ShareMusicDialog.tsx index 5852b24..a85c6e2 100644 --- a/src/components/ShareMusicDialog.tsx +++ b/src/components/ShareMusicDialog.tsx @@ -20,8 +20,6 @@ type SongData = { artist?: string; }; -const songDataApiUrl = "https://nostatus-songdata-api.c-stellar.net/"; - const langCodeToCountry = (lang: LangCode) => { switch (lang) { case "ja": @@ -34,7 +32,7 @@ const langCodeToCountry = (lang: LangCode) => { }; const fetchSongData = async (musicLink: string, lang: LangCode): Promise => { - const apiUrl = new URL(songDataApiUrl); + const apiUrl = new URL(import.meta.env.VITE_SONGDATA_API_URL); const params = new URLSearchParams(); params.set("url", musicLink); diff --git a/src/env.d.ts b/src/env.d.ts deleted file mode 100644 index 8b4bf40..0000000 --- a/src/env.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/// - -interface ImportMetaEnv { - readonly VITE_BUILD_ID: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..70dbba8 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1,10 @@ /// + +interface ImportMetaEnv { + readonly VITE_BUILD_ID: string; + readonly VITE_SONGDATA_API_URL: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} From d2669881d8a0f1e81e9db7fc6e74875465726449 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Fri, 11 Oct 2024 15:58:31 +0900 Subject: [PATCH 4/5] fix lint error (a11y) --- src/App.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index d726000..a2b104c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -45,15 +45,14 @@ export const App = () => { })} >
- {/* biome-ignore lint/a11y/useKeyWithClickEvents: TODO */} -

nostatus

Have an eye on your friends' status.

-
+
From c16564bc49b88a249f7336ffef78fa0bc10babf8 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Fri, 11 Oct 2024 16:51:25 +0900 Subject: [PATCH 5/5] fix fetching song data --- src/components/ShareMusicDialog.tsx | 32 +++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/components/ShareMusicDialog.tsx b/src/components/ShareMusicDialog.tsx index a85c6e2..fc2a912 100644 --- a/src/components/ShareMusicDialog.tsx +++ b/src/components/ShareMusicDialog.tsx @@ -1,10 +1,10 @@ import { css } from "@shadow-panda/styled-system/css"; import { divider, hstack } from "@shadow-panda/styled-system/patterns"; import { t } from "i18next"; -import { atom, useAtomValue } from "jotai"; +import { atom, useAtomValue, useSetAtom } from "jotai"; import { loadable } from "jotai/utils"; import { useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { getI18n } from "react-i18next"; import type { LangCode } from "../locales/i18n"; import { myMusicStatusAtom, updateMyStatus } from "../states/nostr"; import { button } from "../styles/recipes"; @@ -46,20 +46,17 @@ const fetchSongData = async (musicLink: string, lang: LangCode): Promise; }; -const makeMusicDataLoadableAtom = (musicLink: string | undefined, lang: LangCode) => - loadable( - atom(async () => { - if (musicLink === undefined) { - return Promise.resolve(undefined); - } - return fetchSongData(musicLink, lang); - }), - ); +const musicLinkAtom = atom(undefined); -const useSongDataLoadable = (musicLink: string | undefined, lang: LangCode) => { - const songDataLoadableAtom = useMemo(() => makeMusicDataLoadableAtom(musicLink, lang), [musicLink, lang]); - return useAtomValue(songDataLoadableAtom); -}; +const musicDataLoadableAtom = loadable( + atom(async (get) => { + const musicLink = get(musicLinkAtom); + if (musicLink === undefined) { + return Promise.resolve(undefined); + } + return fetchSongData(musicLink, getI18n().language as LangCode); + }), +); type ShareMusicDialogProps = { trigger: React.ReactNode; @@ -71,11 +68,10 @@ export const ShareMusicDialog: React.FC = ({ trigger }) = const [open, setOpen] = useState(false); const closeHeaderMenu = useCloseHeaderMenu(); - const { i18n } = useTranslation(); const [musicLinkInput, setMusicLinkInput] = useState(""); - const [musicLink, setMusicLink] = useState(undefined); + const setMusicLink = useSetAtom(musicLinkAtom); + const songData = useAtomValue(musicDataLoadableAtom); - const songData = useSongDataLoadable(musicLink, i18n.language as LangCode); const newMusicStatus = useMemo(() => { if (songData.state !== "hasData" || songData.data === undefined) { return undefined;