From dc9788dff4fed369654e4f41e0a0e37759f50122 Mon Sep 17 00:00:00 2001 From: Nya Candy Date: Wed, 21 Jun 2023 06:19:18 +0800 Subject: [PATCH] Feat/site player (#642) --- package.json | 2 +- pnpm-lock.yaml | 31 +++++---- src/app/site/[site]/layout.tsx | 3 + src/components/common/SitePlayer.tsx | 44 +++++++++++++ src/components/ui/APlayer.tsx | 90 ++++++++++++++++++++++---- src/lib/i18n/locales/ja/common.json | 4 +- src/lib/i18n/locales/zh-TW/common.json | 6 +- src/lib/i18n/locales/zh/common.json | 4 +- 8 files changed, 154 insertions(+), 30 deletions(-) create mode 100644 src/components/common/SitePlayer.tsx diff --git a/package.json b/package.json index b7b75f0a..d4f77c08 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "@uiw/codemirror-extensions-events": "4.21.3", "@urql/core": "4.0.10", "ahooks": "3.7.7", - "aplayer-react": "1.4.0", + "aplayer": "^1.10.1", "async-lock": "1.4.0", "canvas": "2.11.2", "canvas-confetti": "1.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19d35637..b865fddf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -116,9 +116,9 @@ dependencies: ahooks: specifier: 3.7.7 version: 3.7.7(react@18.2.0) - aplayer-react: - specifier: 1.4.0 - version: 1.4.0(react@18.2.0) + aplayer: + specifier: ^1.10.1 + version: 1.10.1 async-lock: specifier: 1.4.0 version: 1.4.0 @@ -5658,15 +5658,12 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 - /aplayer-react@1.4.0(react@18.2.0): - resolution: {integrity: sha512-gYEWk1ynBSdF7qjMCo1wl2itg595iVj5jdo0Ewep9RhX7aHxdCykwp22t/cwce+KSQ6BAXg4JhUPCsm1oopiLw==} - peerDependencies: - react: ^18.2.0 + /aplayer@1.10.1: + resolution: {integrity: sha512-HAfyxgCUTLAqtYlxzzK9Fyqg6y+kZ9CqT1WfeWE8FSzwspT6oBqWOZHANPHF3RGTtC33IsyEgrfthPDzU5r9kQ==} dependencies: - clsx: 1.2.1 - fast-average-color: 9.3.0 - react: 18.2.0 - use-sync-external-store: 1.2.0(react@18.2.0) + balloon-css: 0.5.2 + promise-polyfill: 7.1.0 + smoothscroll: 0.4.0 dev: false /aproba@2.0.0: @@ -5948,6 +5945,10 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /balloon-css@0.5.2: + resolution: {integrity: sha512-zheJpzwyNrG4t39vusA67v3BYg1HTVXOF8cErPEHzWK88PEOFwgo6Ea9VHOgOWNMgeuOtFVtB73NE2NWl9uDyQ==} + dev: false + /balloon-css@1.2.0: resolution: {integrity: sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==} dev: false @@ -11243,6 +11244,10 @@ packages: resolution: {integrity: sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==} dev: false + /promise-polyfill@7.1.0: + resolution: {integrity: sha512-P6NJ2wU/8fac44ENORsuqT8TiolKGB2u0fEClPtXezn7w5cmLIjM/7mhPlTebke2EPr6tmqZbXvnX0TxwykGrg==} + dev: false + /promise-polyfill@8.3.0: resolution: {integrity: sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==} dev: false @@ -12330,6 +12335,10 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true + /smoothscroll@0.4.0: + resolution: {integrity: sha512-sggQ3U2Un38b3+q/j1P4Y4fCboCtoUIaBYoge+Lb6Xg1H8RTIif/hugVr+ErMtIDpvBbhQfTjtiTeYAfbw1ZGQ==} + dev: false + /sonic-boom@2.8.0: resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} dependencies: diff --git a/src/app/site/[site]/layout.tsx b/src/app/site/[site]/layout.tsx index eb41ba12..84c1d8fb 100644 --- a/src/app/site/[site]/layout.tsx +++ b/src/app/site/[site]/layout.tsx @@ -5,6 +5,7 @@ import { notFound } from "next/navigation" import { Hydrate, dehydrate } from "@tanstack/react-query" import { BlockchainInfo } from "~/components/common/BlockchainInfo" +import { SitePlayerContainer } from "~/components/common/SitePlayer" import Style from "~/components/common/Style" import { BackToTopFAB } from "~/components/site/BackToTopFAB" import SiteFooter from "~/components/site/SiteFooter" @@ -208,6 +209,8 @@ export default async function SiteLayout({ + + ) } diff --git a/src/components/common/SitePlayer.tsx b/src/components/common/SitePlayer.tsx new file mode 100644 index 00000000..ed1a4fa1 --- /dev/null +++ b/src/components/common/SitePlayer.tsx @@ -0,0 +1,44 @@ +"use client" + +// @ts-ignore +import APlayer from "aplayer" +import "aplayer/dist/APlayer.min.css" + +let siteAPlayer: APlayer + +const playerId = "site-aplayer" + +// APlayer Container +export const SitePlayerContainer = () => { + return
+} + +export interface AudioInfo { + name?: string + artist?: string + cover?: string + lrc?: string + url: string +} + +export const sitePlayerAddToPlaylist = (audio: AudioInfo) => { + // Check if player is initialized + if (!siteAPlayer) { + // Initialize + siteAPlayer = new APlayer({ + container: document.getElementById(playerId), + fixed: true, + listFolded: false, + }) + } + // Add + siteAPlayer.list.add(audio) +} + +export const sitePlayerPlayNow = (audio: AudioInfo) => { + // Add to playlist + sitePlayerAddToPlaylist(audio) + // Play now + siteAPlayer.list.switch(siteAPlayer.list.audios.length - 1) + siteAPlayer.play() +} diff --git a/src/components/ui/APlayer.tsx b/src/components/ui/APlayer.tsx index 3fcffd6c..2080d23d 100644 --- a/src/components/ui/APlayer.tsx +++ b/src/components/ui/APlayer.tsx @@ -1,9 +1,14 @@ "use client" -import { APlayer as AplayerReact } from "aplayer-react" -import "aplayer-react/dist/index.css" +import Image from "next/image" import { memo } from "react" +import { + sitePlayerAddToPlaylist, + sitePlayerPlayNow, +} from "~/components/common/SitePlayer" +import { Tooltip } from "~/components/ui/Tooltip" +import { useTranslation } from "~/lib/i18n/client" import { toGateway } from "~/lib/ipfs-parser" const APlayer = memo(function APlayer({ @@ -21,6 +26,8 @@ const APlayer = memo(function APlayer({ cover?: string lrc?: string } & React.AudioHTMLAttributes) { + const { t } = useTranslation("common") + if (!src) return null src = toGateway(src) @@ -31,19 +38,74 @@ const APlayer = memo(function APlayer({ name = name.replace(/^user-content-/, "") } + const audioInfo = { + name: name || "xLog audio", + artist: artist || "", + cover: cover || "/assets/logo.png", + lrc, + url: src, + } + + const addToList = () => { + sitePlayerAddToPlaylist(audioInfo) + } + + const playNow = () => { + sitePlayerPlayNow(audioInfo) + } + return ( - +
+ {/*Info*/} +
+ {/*Cover*/} +
+ {audioInfo.name} +
+ + {/*Name & Artist*/} +
+ {/*Name*/} +
{audioInfo.name}
+ + {/*Artist*/} +
{audioInfo.artist}
+
+
+ + {/*Control buttons*/} +
+ {/*Play Now*/} +
+ + + +
+ + {/*Add to playlist*/} +
+ + + +
+
+
) }) diff --git a/src/lib/i18n/locales/ja/common.json b/src/lib/i18n/locales/ja/common.json index 2dd0cc98..700531be 100644 --- a/src/lib/i18n/locales/ja/common.json +++ b/src/lib/i18n/locales/ja/common.json @@ -55,5 +55,7 @@ "Showcase": "ショーケース", "AI-generated summary": "AIが生成した要約", "Generating": "生成中", - "Show more": "もっと表示する" + "Show more": "もっと表示する", + "Play": "再生", + "Add to playlist": "プレイリストに追加する" } diff --git a/src/lib/i18n/locales/zh-TW/common.json b/src/lib/i18n/locales/zh-TW/common.json index 0d226379..513ce475 100644 --- a/src/lib/i18n/locales/zh-TW/common.json +++ b/src/lib/i18n/locales/zh-TW/common.json @@ -83,5 +83,7 @@ "Refreshing": "重新載入中", "Search for your interest": "搜你所想", "results": "項結果", - "My xLog": "你的 xLog" -} \ No newline at end of file + "My xLog": "你的 xLog", + "Play": "播放", + "Add to playlist": "添加到播放列表" +} diff --git a/src/lib/i18n/locales/zh/common.json b/src/lib/i18n/locales/zh/common.json index a6918022..bab0aae2 100644 --- a/src/lib/i18n/locales/zh/common.json +++ b/src/lib/i18n/locales/zh/common.json @@ -88,5 +88,7 @@ "Comment Without Login": "免登录评论", "Name": "昵称", "Email": "电子邮箱", - "You'll use an official public account for comments and give up blockchain ownership": "你将使用官方公共账号进行评论并放弃区块链所有权" + "You'll use an official public account for comments and give up blockchain ownership": "你将使用官方公共账号进行评论并放弃区块链所有权", + "Play": "播放", + "Add to playlist": "添加到播放列表" }