Compare commits
7 Commits
66a9dbea5c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 153f634a08 | |||
| 1f6c906576 | |||
| c0ead41d21 | |||
| e383876bb0 | |||
| eaf6d47ba0 | |||
| 56c4cf014d | |||
| 2c10ec28aa |
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
**/node_modules/
|
||||||
|
**/dist
|
||||||
|
.git
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
steps:
|
when:
|
||||||
- name: build
|
branch: main
|
||||||
image: node:18-alpine
|
event:
|
||||||
commands:
|
- push
|
||||||
- npm install
|
- manual
|
||||||
- npm run build
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
settings:
|
||||||
|
repo: git.halfbinary.net/${CI_REPO_OWNER}/prettyplayerfe
|
||||||
|
registry: git.halfbinary.net
|
||||||
|
tags: ${CI_PIPELINE_NUMBER}
|
||||||
|
username: ${CI_REPO_OWNER}
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
33
src/App.css
33
src/App.css
@@ -35,6 +35,25 @@
|
|||||||
transition: height 2s;
|
transition: height 2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.player-container {
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
position: sticky;
|
||||||
|
width: 100%;
|
||||||
|
bottom:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expander {
|
||||||
|
align-self: center;
|
||||||
|
height:.75em;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 500%;
|
||||||
|
}
|
||||||
|
|
||||||
.album-title {
|
.album-title {
|
||||||
font-size: larger;
|
font-size: larger;
|
||||||
}
|
}
|
||||||
@@ -42,17 +61,3 @@
|
|||||||
.bold-title {
|
.bold-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.expander {
|
|
||||||
position: absolute;
|
|
||||||
height: 8vmin;
|
|
||||||
width: 8vmin;
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-top: 1vmin;
|
|
||||||
margin-left: 5vmin;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 500%;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ function App() {
|
|||||||
const [albums, setAlbums] = useState(Array<AlbumMetadata>)
|
const [albums, setAlbums] = useState(Array<AlbumMetadata>)
|
||||||
const [selectedAlbum, setSelectedAlbum] = useState("")
|
const [selectedAlbum, setSelectedAlbum] = useState("")
|
||||||
const [albumInfo, setAlbumInfo] = useState<AlbumInfo>()
|
const [albumInfo, setAlbumInfo] = useState<AlbumInfo>()
|
||||||
|
const [isShowAlbumInfo, setIsShowAlbumInfo] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let fetched = fetch(`${hostName}/album`)
|
let fetched = fetch(`${hostName}/album`)
|
||||||
@@ -41,10 +42,14 @@ function App() {
|
|||||||
setSelectedAlbum(event.currentTarget.id)
|
setSelectedAlbum(event.currentTarget.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleAlbumInfoAdjust() {
|
||||||
|
setIsShowAlbumInfo(!isShowAlbumInfo)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"gallery"}>
|
<div className={"gallery"}>
|
||||||
<PhotoContainer imageList={albums} albumClickHandler={handleAlbumClick}/>
|
<PhotoContainer imageList={albums} albumClickHandler={handleAlbumClick}/>
|
||||||
{albumInfo ? <AlbumPlayer albumHash={selectedAlbum} albumInfo={albumInfo} key={selectedAlbum}/> : <div></div> }
|
{albumInfo ? <AlbumPlayer handleAlbumInfoAdjust={handleAlbumInfoAdjust} isShowAlbumInfo={isShowAlbumInfo} albumHash={selectedAlbum} albumInfo={albumInfo} key={selectedAlbum}/> : <div></div> }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import {AlbumInfo} from "../models/AlbumInfo.ts";
|
import {AlbumInfo} from "../models/AlbumInfo.ts";
|
||||||
import TrackListing from "./TrackListing.tsx";
|
import TrackListing from "./TrackListing.tsx";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
interface AlbumInfoDisplayProps {
|
interface AlbumInfoDisplayProps {
|
||||||
albumInfo: AlbumInfo,
|
albumInfo: AlbumInfo,
|
||||||
trackNumber: number
|
trackNumber: number,
|
||||||
|
trackClickHandler: (event: React.MouseEvent<HTMLElement>, trackNumber: number) => void
|
||||||
}
|
}
|
||||||
export default function AlbumInfoDisplay(props: Readonly<AlbumInfoDisplayProps>) {
|
export default function AlbumInfoDisplay(props: Readonly<AlbumInfoDisplayProps>) {
|
||||||
let isVarious = props.albumInfo.albumArtist.startsWith("Various")
|
let isVarious = props.albumInfo.albumArtist.startsWith("Various")
|
||||||
@@ -11,7 +13,7 @@ export default function AlbumInfoDisplay(props: Readonly<AlbumInfoDisplayProps>)
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={`album-title`}>{!isVarious && `${props.albumInfo.albumArtist} - `}{props.albumInfo.albumTitle}</div>
|
<div className={`album-title`}>{!isVarious && `${props.albumInfo.albumArtist} - `}{props.albumInfo.albumTitle}</div>
|
||||||
<TrackListing trackList={props.albumInfo.trackList} isOneArtist={isOneArtist} trackNumber={props.trackNumber}/>
|
<TrackListing trackClickHandler={props.trackClickHandler} trackList={props.albumInfo.trackList} isOneArtist={isOneArtist} trackNumber={props.trackNumber}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import hostName from "../Config.ts";
|
import hostName from "../Config.ts";
|
||||||
import {AlbumInfo} from "../models/AlbumInfo.ts";
|
import {AlbumInfo} from "../models/AlbumInfo.ts";
|
||||||
import AlbumInfoDisplay from "./AlbumInfoDisplay.tsx";
|
import AlbumInfoDisplay from "./AlbumInfoDisplay.tsx";
|
||||||
@@ -9,12 +9,13 @@ import minimize from '/minimize-2.svg'
|
|||||||
interface AlbumPlayerProps {
|
interface AlbumPlayerProps {
|
||||||
albumHash: string,
|
albumHash: string,
|
||||||
albumInfo: AlbumInfo
|
albumInfo: AlbumInfo
|
||||||
|
handleAlbumInfoAdjust: () => void,
|
||||||
|
isShowAlbumInfo: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AlbumPlayer(props: Readonly<AlbumPlayerProps>) {
|
export default function AlbumPlayer(props: Readonly<AlbumPlayerProps>) {
|
||||||
const [trackNum, setTrackNum] = useState<number>(0)
|
const [trackNum, setTrackNum] = useState<number>(0)
|
||||||
const [isAlbumOver, setIsAlbumOver] = useState(false)
|
const [isAlbumOver, setIsAlbumOver] = useState(false)
|
||||||
const [isShowAlbumInfo, setIsShowAlbumInfo] = useState(false)
|
|
||||||
|
|
||||||
let album = props.albumInfo
|
let album = props.albumInfo
|
||||||
|
|
||||||
@@ -30,16 +31,16 @@ export default function AlbumPlayer(props: Readonly<AlbumPlayerProps>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAlbumInfoAdjust() {
|
function handleTrackClick(_: React.MouseEvent<HTMLElement>, trackNumber: number) {
|
||||||
setIsShowAlbumInfo(!isShowAlbumInfo)
|
setTrackNum(trackNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(props.albumHash && album) {
|
if(props.albumHash && album) {
|
||||||
console.log(album)
|
console.log(album)
|
||||||
return (
|
return (
|
||||||
<div className={"player"}>
|
<div className={"player-container"}>
|
||||||
<div className={`expander`} onClick={handleAlbumInfoAdjust} id={"maximizer"}>{isShowAlbumInfo ? <img src={minimize} alt={'minimize song text'}/> : <img src={maximize} alt={'show full album information'}/>}</div>
|
<div className={`expander`} onClick={props.handleAlbumInfoAdjust} id={"maximizer"}>{props.isShowAlbumInfo ? <img src={minimize} alt={'minimize song text'}/> : <img src={maximize} alt={'show full album information'}/>}</div>
|
||||||
{isShowAlbumInfo ? <AlbumInfoDisplay albumInfo={props.albumInfo} trackNumber={trackNum} /> : <TrackInfoDisplay artist={album.trackList[trackNum].trackArtist} track={album.trackList[trackNum].trackTitle} />}
|
<div>{props.isShowAlbumInfo ? <AlbumInfoDisplay albumInfo={props.albumInfo} trackNumber={trackNum} trackClickHandler={handleTrackClick} /> : <TrackInfoDisplay artist={album.trackList[trackNum].trackArtist} track={album.trackList[trackNum].trackTitle} />}</div>
|
||||||
<audio title={album.trackList[trackNum].trackTitle} controls={true} autoPlay={true} preload={"metadata"}
|
<audio title={album.trackList[trackNum].trackTitle} controls={true} autoPlay={true} preload={"metadata"}
|
||||||
src={`${hostName}/music/album/${props.albumHash}/track/${trackNum}`}
|
src={`${hostName}/music/album/${props.albumHash}/track/${trackNum}`}
|
||||||
onEnded={handleNextTrack} />
|
onEnded={handleNextTrack} />
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import {AlbumTrackInfo} from "../models/AlbumTrackInfo.ts";
|
import {AlbumTrackInfo} from "../models/AlbumTrackInfo.ts";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
interface TrackListingProps {
|
interface TrackListingProps {
|
||||||
trackList: AlbumTrackInfo[],
|
trackList: AlbumTrackInfo[],
|
||||||
isOneArtist: boolean,
|
isOneArtist: boolean,
|
||||||
trackNumber: number
|
trackNumber: number,
|
||||||
|
trackClickHandler: (event: React.MouseEvent<HTMLElement>, trackNumber: number) => void
|
||||||
}
|
}
|
||||||
export default function TrackListing(props: Readonly<TrackListingProps>) {
|
export default function TrackListing(props: Readonly<TrackListingProps>) {
|
||||||
return (
|
return (
|
||||||
@@ -12,7 +14,7 @@ export default function TrackListing(props: Readonly<TrackListingProps>) {
|
|||||||
let rawKeyString = `${track.trackNumber}${track.trackArtist}${track.trackTitle}`
|
let rawKeyString = `${track.trackNumber}${track.trackArtist}${track.trackTitle}`
|
||||||
let isCurrentTrack = index===props.trackNumber
|
let isCurrentTrack = index===props.trackNumber
|
||||||
return (
|
return (
|
||||||
<div key={rawKeyString} className={ isCurrentTrack ? `bold-title` : ``}>{track.trackNumber}. {!props.isOneArtist && `${track.trackArtist} - `}{track.trackTitle}</div>
|
<div onClick={(e) => props.trackClickHandler(e, index)} key={rawKeyString} className={ isCurrentTrack ? `bold-title` : ``}>{track.trackNumber}. {!props.isOneArtist && `${track.trackArtist} - `}{track.trackTitle}</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user