Player.jsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React, { useState } from "react";
  2. import { useSelector, useDispatch } from "react-redux";
  3. import {
  4. actionTogglePlay,
  5. actionToggleRepeat,
  6. actionSetVolume,
  7. actionSetCurrentTime,
  8. actionPrevTrack,
  9. actionNextTrack,
  10. } from "../../redux/actions/creators/audio";
  11. import "./style.scoped.scss";
  12. import { removeAudioExtension } from "../../utils/regex";
  13. import CollapseIcon from "../../assets/collapse_icon.svg";
  14. import ShuffleIcon from "../../assets/shuffle_icon.svg";
  15. import PreviousIcon from "../../assets/previous_icon.svg";
  16. import NextIcon from "../../assets/next_icon.svg";
  17. import PlayIcon from "../../assets/play_icon.svg";
  18. import StopIcon from "../../assets/stop_icon.svg";
  19. import RepeatIcon from "../../assets/repeat_icon.svg";
  20. import VolumeUpIcon from "../../assets/volume_up_icon.svg";
  21. import VolumeStopIcon from "../../assets/volume_stop_icon.svg";
  22. import { secondsToHMS } from "../../utils";
  23. import { createSelector } from "reselect";
  24. const whiteFilter = `invert(100%) sepia(0%) saturate(7500%) hue-rotate(116deg)
  25. brightness(109%) contrast(109%)`;
  26. const darkFilter = `invert(48%) sepia(3%) saturate(4%) hue-rotate(326deg) brightness(110%) contrast(78%)`;
  27. const playerState = createSelector(
  28. (store) => store.audio,
  29. (audio) => audio
  30. );
  31. const Player = () => {
  32. const dispatch = useDispatch();
  33. const state = useSelector(playerState);
  34. const title = state.track
  35. ? state.track.id3.title ||
  36. removeAudioExtension(state.track.originalFileName)
  37. : null;
  38. const [isCollapsed, setIsCollapsed] = useState(false);
  39. return (
  40. <div
  41. className="player"
  42. style={{
  43. height: isCollapsed ? "30px" : "80px",
  44. }}
  45. >
  46. <div className="header">
  47. <p className="duration">{secondsToHMS(state.currentTime)}</p>
  48. <input
  49. className="audio"
  50. type={"range"}
  51. min={0}
  52. max={state.duration}
  53. value={state.currentTime}
  54. onChange={(e) => {
  55. dispatch(actionSetCurrentTime(+e.target.value));
  56. }}
  57. />
  58. <img
  59. className="button-collapse"
  60. src={CollapseIcon}
  61. style={{
  62. filter: isCollapsed ? darkFilter : whiteFilter,
  63. }}
  64. onClick={() => setIsCollapsed(!isCollapsed)}
  65. />
  66. </div>
  67. {!isCollapsed ? (
  68. <div className="footer">
  69. <div className="info">
  70. <p className="track-name">{title ?? "Here is track"}</p>
  71. <p className="playlist-name">Here is playlist</p>
  72. </div>
  73. <div className="main-buttons">
  74. <img className="shuffle-button" src={ShuffleIcon} />
  75. <img
  76. className="previous-button"
  77. src={PreviousIcon}
  78. onClick={() => dispatch(actionPrevTrack())}
  79. />
  80. <img
  81. className="status-button"
  82. src={state.isPlaying ? StopIcon : PlayIcon}
  83. onClick={() =>
  84. dispatch(
  85. actionTogglePlay(
  86. state.isPlaying ? false : true
  87. )
  88. )
  89. }
  90. />
  91. <img
  92. className="next-button"
  93. src={NextIcon}
  94. onClick={() => dispatch(actionNextTrack())}
  95. />
  96. <img
  97. className="repeat-button"
  98. src={RepeatIcon}
  99. style={{
  100. filter: state.isRepeated
  101. ? whiteFilter
  102. : darkFilter,
  103. }}
  104. onClick={() =>
  105. dispatch(actionToggleRepeat(!state.isRepeated))
  106. }
  107. />
  108. </div>
  109. <div className="volume-settings">
  110. <img
  111. className="button-volume"
  112. src={state.volume ? VolumeUpIcon : VolumeStopIcon}
  113. onClick={() =>
  114. dispatch(actionSetVolume(state.volume ? 0 : 1))
  115. }
  116. />
  117. <input
  118. className="volume"
  119. type={"range"}
  120. min={0}
  121. max={1}
  122. step={0.01}
  123. value={state.volume}
  124. onChange={(e) => {
  125. dispatch(actionSetVolume(+e.target.value));
  126. }}
  127. />
  128. </div>
  129. </div>
  130. ) : null}
  131. </div>
  132. );
  133. };
  134. export default Player;