diff --git a/packages/app/src/components/EmbbededMediaPlayer/index.jsx b/packages/app/src/components/EmbbededMediaPlayer/index.jsx deleted file mode 100755 index 6d1207aa..00000000 --- a/packages/app/src/components/EmbbededMediaPlayer/index.jsx +++ /dev/null @@ -1,549 +0,0 @@ -import React from "react" -import * as antd from "antd" -import Slider from "@mui/material/Slider" -import classnames from "classnames" - -import UseAnimations from "react-useanimations" -import LoadingAnimation from "react-useanimations/lib/loading" - -import LikeButton from "components/LikeButton" -import { Icons, createIconRender } from "components/Icons" - -import "./index.less" - -// TODO: Queue view -const AudioVolume = (props) => { - return
- { - return `${Math.round(value * 100)}%` - } - }} - vertical - /> -
-} - -export class SeekBar extends React.Component { - state = { - timeText: "00:00", - durationText: "00:00", - sliderTime: 0, - sliderLock: false, - } - - handleSeek = (value) => { - if (value > 0) { - // calculate the duration of the audio - const duration = app.cores.player.duration() - - // calculate the seek of the audio - const seek = (value / 100) * duration - - app.cores.player.seek(seek) - } else { - app.cores.player.seek(0) - } - } - - calculateDuration = () => { - // get current audio duration - const audioDuration = app.cores.player.duration() - - if (isNaN(audioDuration)) { - return - } - - console.log(`Audio duration: ${audioDuration}`) - - // set duration - this.setState({ - durationText: this.seekToTimeLabel(audioDuration) - }) - } - - calculateTime = () => { - // get current audio seek - const seek = app.cores.player.seek() - - // set time - this.setState({ - timeText: this.seekToTimeLabel(seek) - }) - } - - seekToTimeLabel = (value) => { - // convert seek to minutes and seconds - const minutes = Math.floor(value / 60) - - // add leading zero if minutes is less than 10 - const minutesString = minutes < 10 ? `0${minutes}` : minutes - - // get seconds - const seconds = Math.floor(value - minutes * 60) - - // add leading zero if seconds is less than 10 - const secondsString = seconds < 10 ? `0${seconds}` : seconds - - return `${minutesString}:${secondsString}` - } - - updateProgressBar = () => { - if (this.state.sliderLock) { - return - } - - const seek = app.cores.player.seek() - const duration = app.cores.player.duration() - - const percent = (seek / duration) * 100 - - this.setState({ - sliderTime: percent - }) - } - - updateAll = () => { - this.calculateTime() - this.updateProgressBar() - } - - events = { - "player.status.update": (status) => { - console.log(`Player status updated: ${status}`) - - switch (status) { - case "stopped": - this.setState({ - timeText: "00:00", - durationText: "00:00", - sliderTime: 0, - }) - - break - case "playing": - this.updateAll() - this.calculateDuration() - - break - default: - break - } - }, - "player.current.update": (currentAudioManifest) => { - console.log(`Player current audio updated:`, currentAudioManifest) - - this.updateAll() - - this.setState({ - timeText: "00:00", - sliderTime: 0, - }) - - this.calculateDuration() - }, - "player.duration.update": (duration) => { - console.log(`Player duration updated: ${duration}`) - - this.calculateDuration() - }, - "player.seek.update": (seek) => { - console.log(`Player seek updated: ${seek}`) - - this.calculateTime() - this.updateAll() - }, - } - - tick = () => { - if (this.props.playing || this.props.streamMode) { - this.interval = setInterval(() => { - this.updateAll() - }, 1000) - } else { - if (this.interval) { - clearInterval(this.interval) - } - } - } - - componentDidMount = () => { - this.calculateDuration() - this.tick() - - for (const [event, callback] of Object.entries(this.events)) { - app.eventBus.on(event, callback) - } - } - - componentWillUnmount = () => { - for (const [event, callback] of Object.entries(this.events)) { - app.eventBus.off(event, callback) - } - } - - componentDidUpdate = (prevProps, prevState) => { - if (this.props.playing !== prevProps.playing) { - this.tick() - } - } - - render() { - return
-
- { - this.setState({ - sliderTime: value, - sliderLock: true - }) - }} - onChangeCommitted={() => { - this.setState({ - sliderLock: false - }) - - this.handleSeek(this.state.sliderTime) - - if (!this.props.playing) { - app.cores.player.playback.play() - } - }} - valueLabelDisplay="auto" - valueLabelFormat={(value) => { - return this.seekToTimeLabel((value / 100) * app.cores.player.duration()) - }} - /> -
-
-
- {this.state.timeText} -
-
- { - this.props.streamMode ? Live : {this.state.durationText} - } -
-
-
- } -} - -const AudioPlayerChangeModeButton = (props) => { - const [mode, setMode] = React.useState(app.cores.player.playback.mode()) - - const modeToIcon = { - "normal": "MdArrowForward", - "repeat": "MdRepeat", - "shuffle": "MdShuffle", - } - - const onClick = () => { - const modes = Object.keys(modeToIcon) - - const newMode = modes[(modes.indexOf(mode) + 1) % modes.length] - - app.cores.player.playback.mode(newMode) - - setMode(newMode) - } - - return -} - -export default class AudioPlayer extends React.Component { - state = { - loading: app.cores.player.getState("loading") ?? false, - currentPlaying: app.cores.player.getState("currentAudioManifest"), - playbackStatus: app.cores.player.getState("playbackStatus") ?? "stopped", - audioMuted: app.cores.player.getState("audioMuted") ?? false, - audioVolume: app.cores.player.getState("audioVolume") ?? 0.3, - bpm: app.cores.player.getState("trackBPM") ?? 0, - showControls: false, - minimized: false, - streamMode: false, - - syncModeLocked: app.cores.player.getState("syncModeLocked"), - syncMode: app.cores.player.getState("syncMode"), - } - - events = { - "player.syncModeLocked.update": (to) => { - this.setState({ syncModeLocked: to }) - }, - "player.syncMode.update": (to) => { - this.setState({ syncMode: to }) - }, - "player.livestream.update": (data) => { - this.setState({ streamMode: data }) - }, - "player.bpm.update": (data) => { - this.setState({ bpm: data }) - }, - "player.loading.update": (data) => { - this.setState({ loading: data }) - }, - "player.status.update": (data) => { - this.setState({ playbackStatus: data }) - }, - "player.current.update": (data) => { - this.setState({ currentPlaying: data }) - }, - "player.mute.update": (data) => { - this.setState({ audioMuted: data }) - }, - "player.volume.update": (data) => { - this.setState({ audioVolume: data }) - }, - "player.minimized.update": (minimized) => { - this.setState({ minimized }) - } - } - - componentDidMount = async () => { - Object.entries(this.events).forEach(([event, callback]) => { - app.eventBus.on(event, callback) - }) - } - - componentWillUnmount() { - Object.entries(this.events).forEach(([event, callback]) => { - app.eventBus.off(event, callback) - }) - } - - onMouse = (event) => { - const { type } = event - - if (type === "mouseenter") { - this.setState({ showControls: true }) - } else if (type === "mouseleave") { - this.setState({ showControls: false }) - } - } - - minimize = () => { - app.cores.player.minimize() - } - - close = () => { - app.cores.player.close() - } - - openVisualizer = () => { - app.setLocation("/lyrics") - } - - inviteSync = () => { - app.cores.sync.music.createSyncRoom() - } - - updateVolume = (value) => { - app.cores.player.volume(value) - } - - toogleMute = () => { - app.cores.player.toogleMute() - } - - onClickPlayButton = () => { - if (this.state.streamMode) { - return app.cores.player.playback.stop() - } - - app.cores.player.playback.toogle() - } - - onClickPreviousButton = () => { - app.cores.player.playback.previous() - } - - onClickNextButton = () => { - app.cores.player.playback.next() - } - - onClickLikeButton = () => { - // TODO: Like - - console.log("Like") - - this.setState({ liked: !this.state.liked }) - } - - render() { - const { - loading, - currentPlaying, - playbackStatus, - audioMuted, - audioVolume, - } = this.state - - return
-
- } - onClick={this.minimize} - shape="circle" - /> - - { - !this.state.syncModeLocked && !this.state.syncMode && } - onClick={this.inviteSync} - shape="circle" - /> - } - - } - onClick={this.openVisualizer} - shape="circle" - /> - - } - onClick={this.close} - shape="square" - /> -
-
-
-
-
-
-

- { - currentPlaying?.title - ? currentPlaying?.title - : (loading ? "Loading..." : (currentPlaying?.title ?? "Untitled")) - } -

-
-
- { - currentPlaying?.artist &&
-

- {currentPlaying?.artist ?? "Unknown"} -

-
- } - - -
-
-
- -
- - } - onClick={this.onClickPreviousButton} - disabled={this.state.syncModeLocked} - /> - : playbackStatus === "playing" ? : } - onClick={this.onClickPlayButton} - className="playButton" - disabled={this.state.syncModeLocked} - > - { - loading &&
- -
- } -
- } - onClick={this.onClickNextButton} - disabled={this.state.syncModeLocked} - /> - -
- { - audioMuted - ? - : - } -
-
-
- - -
-
- } -} \ No newline at end of file diff --git a/packages/app/src/components/Player/AudioVolume/index.jsx b/packages/app/src/components/Player/AudioVolume/index.jsx new file mode 100644 index 00000000..22f211cb --- /dev/null +++ b/packages/app/src/components/Player/AudioVolume/index.jsx @@ -0,0 +1,23 @@ +import React from "react" +import * as antd from "antd" + +import "./index.less" + +export default (props) => { + return
+ { + return `${Math.round(value * 100)}%` + } + }} + vertical + /> +
+} diff --git a/packages/app/src/components/Player/AudioVolume/index.less b/packages/app/src/components/Player/AudioVolume/index.less new file mode 100644 index 00000000..fe25d856 --- /dev/null +++ b/packages/app/src/components/Player/AudioVolume/index.less @@ -0,0 +1,14 @@ +.ant-popover-inner-content { + height: fit-content; + + display: flex; + flex-direction: column; + + align-items: center; + justify-content: center; + + .player-volume_slider { + height: 150px; + padding-bottom: 10px; + } +} \ No newline at end of file diff --git a/packages/app/src/components/BackgroundMediaPlayer/index.jsx b/packages/app/src/components/Player/BackgroundMediaPlayer/index.jsx similarity index 100% rename from packages/app/src/components/BackgroundMediaPlayer/index.jsx rename to packages/app/src/components/Player/BackgroundMediaPlayer/index.jsx diff --git a/packages/app/src/components/BackgroundMediaPlayer/index.less b/packages/app/src/components/Player/BackgroundMediaPlayer/index.less similarity index 100% rename from packages/app/src/components/BackgroundMediaPlayer/index.less rename to packages/app/src/components/Player/BackgroundMediaPlayer/index.less diff --git a/packages/app/src/components/Player/ChangeModeButton/index.jsx b/packages/app/src/components/Player/ChangeModeButton/index.jsx new file mode 100644 index 00000000..a2a78f37 --- /dev/null +++ b/packages/app/src/components/Player/ChangeModeButton/index.jsx @@ -0,0 +1,31 @@ +import React from "react" +import * as antd from "antd" + +import { Icons, createIconRender } from "components/Icons" + +export default (props) => { + const [mode, setMode] = React.useState(app.cores.player.playback.mode()) + + const modeToIcon = { + "normal": "MdArrowForward", + "repeat": "MdRepeat", + "shuffle": "MdShuffle", + } + + const onClick = () => { + const modes = Object.keys(modeToIcon) + + const newMode = modes[(modes.indexOf(mode) + 1) % modes.length] + + app.cores.player.playback.mode(newMode) + + setMode(newMode) + } + + return +} diff --git a/packages/app/src/components/Player/Controls/index.jsx b/packages/app/src/components/Player/Controls/index.jsx new file mode 100644 index 00000000..6ea0ce1d --- /dev/null +++ b/packages/app/src/components/Player/Controls/index.jsx @@ -0,0 +1,101 @@ +import React from "react" +import * as antd from "antd" + +import UseAnimations from "react-useanimations" +import LoadingAnimation from "react-useanimations/lib/loading" + +import { Icons } from "components/Icons" + +import AudioVolume from "components/Player/AudioVolume" +import AudioPlayerChangeModeButton from "components/Player/ChangeModeButton" + +import "./index.less" + +export default ({ + className, + controls, + syncModeLocked = false, + syncMode = false, + streamMode, + playbackStatus, + onVolumeUpdate, + onMuteUpdate, + audioVolume = 0.3, + audioMuted = false, + loading = false, +} = {}) => { + const onClickActionsButton = (event) => { + if (typeof controls !== "object") { + console.warn("[AudioPlayer] onClickActionsButton: props.controls is not an object") + + return false + } + + if (typeof controls[event] !== "function") { + console.warn(`[AudioPlayer] onClickActionsButton: ${event} is not a function`) + + return false + } + + return controls[event]() + } + + return
+ + } + onClick={() => onClickActionsButton("previous")} + disabled={syncModeLocked} + /> + : playbackStatus === "playing" ? : } + onClick={() => onClickActionsButton("toogle")} + className="playButton" + disabled={syncModeLocked} + > + { + loading &&
+ +
+ } +
+ } + onClick={() => onClickActionsButton("next")} + disabled={syncModeLocked} + /> + +
+ { + audioMuted + ? + : + } +
+
+
+} \ No newline at end of file diff --git a/packages/app/src/components/Player/Controls/index.less b/packages/app/src/components/Player/Controls/index.less new file mode 100644 index 00000000..31775cae --- /dev/null +++ b/packages/app/src/components/Player/Controls/index.less @@ -0,0 +1,61 @@ +.player-controls { + display: inline-flex; + flex-direction: row; + + align-items: center; + justify-content: space-evenly; + + width: 100%; + + svg { + color: var(--text-color); + margin: 0 !important; + } + + .playButton { + position: relative; + + display: flex; + + align-items: center; + justify-content: center; + + .loadCircle { + position: absolute; + + z-index: 330; + + top: 0; + right: 0; + left: 0; + + width: 100%; + height: 100%; + + margin: auto; + + align-self: center; + justify-self: center; + + transform: scale(1.5); + + svg { + width: 100%; + height: 100%; + + path { + stroke: var(--text-color); + stroke-width: 1; + } + } + } + } + + .muteButton { + padding: 10px; + + svg { + font-size: 1rem; + } + } +} \ No newline at end of file diff --git a/packages/app/src/components/Player/MediaPlayer/index.jsx b/packages/app/src/components/Player/MediaPlayer/index.jsx new file mode 100755 index 00000000..d81768c4 --- /dev/null +++ b/packages/app/src/components/Player/MediaPlayer/index.jsx @@ -0,0 +1,240 @@ +import React from "react" +import * as antd from "antd" +import classnames from "classnames" + +import LikeButton from "components/LikeButton" +import { Icons } from "components/Icons" + +import SeekBar from "components/Player/SeekBar" +import Controls from "components/Player/Controls" + +import "./index.less" + +// TODO: Queue view +export default class AudioPlayer extends React.Component { + state = { + loading: app.cores.player.getState("loading") ?? false, + currentPlaying: app.cores.player.getState("currentAudioManifest"), + playbackStatus: app.cores.player.getState("playbackStatus") ?? "stopped", + audioMuted: app.cores.player.getState("audioMuted") ?? false, + audioVolume: app.cores.player.getState("audioVolume") ?? 0.3, + bpm: app.cores.player.getState("trackBPM") ?? 0, + showControls: false, + minimized: false, + streamMode: false, + + syncModeLocked: app.cores.player.getState("syncModeLocked"), + syncMode: app.cores.player.getState("syncMode"), + } + + events = { + "player.syncModeLocked.update": (to) => { + this.setState({ syncModeLocked: to }) + }, + "player.syncMode.update": (to) => { + this.setState({ syncMode: to }) + }, + "player.livestream.update": (data) => { + this.setState({ streamMode: data }) + }, + "player.bpm.update": (data) => { + this.setState({ bpm: data }) + }, + "player.loading.update": (data) => { + this.setState({ loading: data }) + }, + "player.status.update": (data) => { + this.setState({ playbackStatus: data }) + }, + "player.current.update": (data) => { + this.setState({ currentPlaying: data }) + }, + "player.mute.update": (data) => { + this.setState({ audioMuted: data }) + }, + "player.volume.update": (data) => { + this.setState({ audioVolume: data }) + }, + "player.minimized.update": (minimized) => { + this.setState({ minimized }) + } + } + + componentDidMount = async () => { + Object.entries(this.events).forEach(([event, callback]) => { + app.eventBus.on(event, callback) + }) + } + + componentWillUnmount() { + Object.entries(this.events).forEach(([event, callback]) => { + app.eventBus.off(event, callback) + }) + } + + onMouse = (event) => { + const { type } = event + + if (type === "mouseenter") { + this.setState({ showControls: true }) + } else if (type === "mouseleave") { + this.setState({ showControls: false }) + } + } + + minimize = () => { + app.cores.player.minimize() + } + + close = () => { + app.cores.player.close() + } + + openVisualizer = () => { + app.setLocation("/lyrics") + } + + inviteSync = () => { + app.cores.sync.music.createSyncRoom() + } + + updateVolume = (value) => { + app.cores.player.volume(value) + } + + toogleMute = () => { + app.cores.player.toogleMute() + } + + onClickPlayButton = () => { + if (this.state.streamMode) { + return app.cores.player.playback.stop() + } + + app.cores.player.playback.toogle() + } + + onClickPreviousButton = () => { + app.cores.player.playback.previous() + } + + onClickNextButton = () => { + app.cores.player.playback.next() + } + + onClickLikeButton = () => { + // TODO: Like + + console.log("Like") + + this.setState({ liked: !this.state.liked }) + } + + render() { + const { + loading, + currentPlaying, + playbackStatus, + audioMuted, + audioVolume, + } = this.state + + return
+
+ } + onClick={this.minimize} + shape="circle" + /> + + { + !this.state.syncModeLocked && !this.state.syncMode && } + onClick={this.inviteSync} + shape="circle" + /> + } + + } + onClick={this.openVisualizer} + shape="circle" + /> + + } + onClick={this.close} + shape="square" + /> +
+
+
+
+
+
+

+ { + currentPlaying?.title + ? currentPlaying?.title + : (loading ? "Loading..." : (currentPlaying?.title ?? "Untitled")) + } +

+
+
+ { + currentPlaying?.artist &&
+

+ {currentPlaying?.artist ?? "Unknown"} +

+
+ } + + +
+
+
+ + + + +
+
+ } +} \ No newline at end of file diff --git a/packages/app/src/components/EmbbededMediaPlayer/index.less b/packages/app/src/components/Player/MediaPlayer/index.less similarity index 59% rename from packages/app/src/components/EmbbededMediaPlayer/index.less rename to packages/app/src/components/Player/MediaPlayer/index.less index e2d188af..10c5a885 100755 --- a/packages/app/src/components/EmbbededMediaPlayer/index.less +++ b/packages/app/src/components/Player/MediaPlayer/index.less @@ -177,145 +177,6 @@ } } } - - .controls { - display: inline-flex; - flex-direction: row; - - align-items: center; - justify-content: space-evenly; - - width: 100%; - - svg { - color: var(--text-color); - margin: 0 !important; - } - - .playButton { - position: relative; - - display: flex; - - align-items: center; - justify-content: center; - - .loadCircle { - position: absolute; - - z-index: 330; - - top: 0; - right: 0; - left: 0; - - width: 100%; - height: 100%; - - margin: auto; - - align-self: center; - justify-self: center; - - transform: scale(1.5); - - svg { - width: 100%; - height: 100%; - - path { - stroke: var(--text-color); - stroke-width: 1; - } - } - } - } - - .muteButton { - padding: 10px; - - svg { - font-size: 1rem; - } - } - } - } - - .status { - z-index: 330; - - display: flex; - flex-direction: column; - - align-items: center; - justify-content: center; - - align-self: center; - - width: 90%; - height: 100%; - - margin: 20px 0 10px 0; - - border-radius: 8px; - - transition: all 150ms ease-in-out; - - &.hidden { - height: 0px; - opacity: 0; - pointer-events: none; - } - - .progress { - width: 100%; - height: 100%; - - transition: all 150ms ease-in-out; - - &.hidden { - opacity: 0; - height: 0; - pointer-events: none; - } - } - - .timers { - display: inline-flex; - flex-direction: row; - - width: 100%; - height: fit-content; - - justify-content: space-between; - align-items: center; - } - - h1, - h2, - h3, - h4, - h5, - h6, - p, - span { - color: var(--text-color); - } - } -} - -.ant-popover-inner-content { - height: fit-content; - - display: flex; - flex-direction: column; - - align-items: center; - justify-content: center; - - .volumeSlider { - height: 250px; - padding-bottom: 10px; } } diff --git a/packages/app/src/components/Player/SeekBar/index.jsx b/packages/app/src/components/Player/SeekBar/index.jsx new file mode 100644 index 00000000..3459a61a --- /dev/null +++ b/packages/app/src/components/Player/SeekBar/index.jsx @@ -0,0 +1,228 @@ +import React from "react" +import * as antd from "antd" +import Slider from "@mui/material/Slider" +import classnames from "classnames" + +import "./index.less" + +export default class SeekBar extends React.Component { + state = { + timeText: "00:00", + durationText: "00:00", + sliderTime: 0, + sliderLock: false, + } + + handleSeek = (value) => { + if (value > 0) { + // calculate the duration of the audio + const duration = app.cores.player.duration() + + // calculate the seek of the audio + const seek = (value / 100) * duration + + app.cores.player.seek(seek) + } else { + app.cores.player.seek(0) + } + } + + calculateDuration = () => { + // get current audio duration + const audioDuration = app.cores.player.duration() + + if (isNaN(audioDuration)) { + return + } + + console.log(`Audio duration: ${audioDuration}`) + + // set duration + this.setState({ + durationText: this.seekToTimeLabel(audioDuration) + }) + } + + calculateTime = () => { + // get current audio seek + const seek = app.cores.player.seek() + + // set time + this.setState({ + timeText: this.seekToTimeLabel(seek) + }) + } + + seekToTimeLabel = (value) => { + // convert seek to minutes and seconds + const minutes = Math.floor(value / 60) + + // add leading zero if minutes is less than 10 + const minutesString = minutes < 10 ? `0${minutes}` : minutes + + // get seconds + const seconds = Math.floor(value - minutes * 60) + + // add leading zero if seconds is less than 10 + const secondsString = seconds < 10 ? `0${seconds}` : seconds + + return `${minutesString}:${secondsString}` + } + + updateProgressBar = () => { + if (this.state.sliderLock) { + return + } + + const seek = app.cores.player.seek() + const duration = app.cores.player.duration() + + const percent = (seek / duration) * 100 + + this.setState({ + sliderTime: percent + }) + } + + updateAll = () => { + this.calculateTime() + this.updateProgressBar() + } + + events = { + "player.status.update": (status) => { + console.log(`Player status updated: ${status}`) + + switch (status) { + case "stopped": + this.setState({ + timeText: "00:00", + durationText: "00:00", + sliderTime: 0, + }) + + break + case "playing": + this.updateAll() + this.calculateDuration() + + break + default: + break + } + }, + "player.current.update": (currentAudioManifest) => { + console.log(`Player current audio updated:`, currentAudioManifest) + + this.updateAll() + + this.setState({ + timeText: "00:00", + sliderTime: 0, + }) + + this.calculateDuration() + }, + "player.duration.update": (duration) => { + console.log(`Player duration updated: ${duration}`) + + this.calculateDuration() + }, + "player.seek.update": (seek) => { + console.log(`Player seek updated: ${seek}`) + + this.calculateTime() + this.updateAll() + }, + } + + tick = () => { + if (this.props.playing || this.props.streamMode) { + this.interval = setInterval(() => { + this.updateAll() + }, 1000) + } else { + if (this.interval) { + clearInterval(this.interval) + } + } + } + + componentDidMount = () => { + this.calculateDuration() + this.tick() + + for (const [event, callback] of Object.entries(this.events)) { + app.eventBus.on(event, callback) + } + } + + componentWillUnmount = () => { + for (const [event, callback] of Object.entries(this.events)) { + app.eventBus.off(event, callback) + } + } + + componentDidUpdate = (prevProps, prevState) => { + if (this.props.playing !== prevProps.playing) { + this.tick() + } + } + + render() { + return
+
+ { + this.setState({ + sliderTime: value, + sliderLock: true + }) + }} + onChangeCommitted={() => { + this.setState({ + sliderLock: false + }) + + this.handleSeek(this.state.sliderTime) + + if (!this.props.playing) { + app.cores.player.playback.play() + } + }} + valueLabelDisplay="auto" + valueLabelFormat={(value) => { + return this.seekToTimeLabel((value / 100) * app.cores.player.duration()) + }} + /> +
+
+
+ {this.state.timeText} +
+
+ { + this.props.streamMode ? Live : {this.state.durationText} + } +
+
+
+ } +} diff --git a/packages/app/src/components/Player/SeekBar/index.less b/packages/app/src/components/Player/SeekBar/index.less new file mode 100644 index 00000000..4cdcd156 --- /dev/null +++ b/packages/app/src/components/Player/SeekBar/index.less @@ -0,0 +1,61 @@ +.player-seek_bar { + z-index: 330; + + display: flex; + flex-direction: column; + + align-items: center; + justify-content: center; + + align-self: center; + + width: 90%; + height: 100%; + + margin: 20px 0 10px 0; + + border-radius: 8px; + + transition: all 150ms ease-in-out; + + &.hidden { + height: 0px; + opacity: 0; + pointer-events: none; + } + + .progress { + width: 100%; + height: 100%; + + transition: all 150ms ease-in-out; + + &.hidden { + opacity: 0; + height: 0; + pointer-events: none; + } + } + + .timers { + display: inline-flex; + flex-direction: row; + + width: 100%; + height: fit-content; + + justify-content: space-between; + align-items: center; + } + + h1, + h2, + h3, + h4, + h5, + h6, + p, + span { + color: var(--text-color); + } +} \ No newline at end of file