[feature-154] volume slider finished

This commit is contained in:
MathieuG-P
2023-03-04 13:41:48 +01:00
parent 8a168d20b3
commit c406dfee79
6 changed files with 84 additions and 46 deletions
@@ -16,6 +16,8 @@ export function Modal() {
const {firstColor, secondColor} = useThemeColor();
console.log(ModalComponent, resolver);
useEffect(() => {
const onEscape = (e: KeyboardEvent) => {
@@ -38,7 +40,7 @@ export function Modal() {
return (
<AnimatePresence>
{ModalComponent && (
{ModalComponent && resolver && (
<div className="top-0 absolute w-screen h-screen flex content-center items-center justify-center z-[90]">
<motion.span key="modal-overlay" onClick={() => modalSevice.resolve({exitCode: ModalExitCode.NO_CHOICE})} className="absolute top-0 bottom-0 right-0 left-0 bg-black" initial={{opacity: 0}} animate={{opacity: ModalComponent && .60}} exit={{opacity: 0}} transition={{duration: .2}}/>
<motion.div key="modal" initial={{y: "100vh"}} animate={{y: 0}} exit={{y: "100vh"}}>
@@ -3,7 +3,7 @@ import { CSSProperties } from "react";
export function VolumeDownIcon(props: {className?: string, style?: CSSProperties}) {
return (
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" fill="currentColor">
<path d="M229.826 702.696q-16.326 0-27.181-10.855t-10.855-27.022V487.181q0-16.167 10.855-27.101 10.855-10.935 27.181-10.935h125.949l144.928-144.928q17.978-17.819 41.268-8.123 23.29 9.695 23.29 34.978v489.697q0 25.442-23.29 35.137-23.29 9.696-41.268-8.282L355.775 702.696H229.826Zm402.101 41.029V406.942q52.196 18.971 84.24 65.609Q748.21 519.188 748.21 576q0 57.478-32.043 103.036-32.044 45.558-84.24 64.689ZM489.348 427.818l-100.573 97.24H267.703v101.884h121.072l100.573 97.907V427.818ZM377.072 576Z"/>
<path d="M251.283 675.999q-13.564 0-22.423-8.859-8.859-8.859-8.859-22.423V507.283q0-13.564 8.859-22.423 8.859-8.859 22.423-8.859h117.179L486.794 357.67q14.769-14.769 33.987-6.91 19.218 7.858 19.218 28.781v392.661q0 21.18-19.218 29.038-19.218 7.859-33.987-6.91L368.462 675.999H251.283Zm374.358 49.949V424.463q43.05 19.102 68.704 60.551 25.654 41.448 25.654 90.986 0 50.205-25.654 90.525-25.654 40.32-68.704 59.423ZM489.744 429.436l-99.129 96.82H270.256v99.488h120.359l99.129 97.23V429.436ZM378.923 576Z"/>
</svg>
)
}
@@ -3,7 +3,7 @@ import { CSSProperties } from "react";
export function VolumeOffIcon(props: {className?: string, style?: CSSProperties}) {
return (
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" fill="currentColor">
<path d="M783.037 981.102 679.261 877.246q-16.645 11.044-34.21 20.493-17.566 9.45-36.544 16.225-17.572 6.159-32.862-5.04-15.29-11.199-15.29-31.474 0-8.682 4.609-15.649 4.608-6.967 12.797-9.873 13.391-4.522 26.761-10.862 13.37-6.341 24.826-14.45L480.355 676.637v144.132q0 25.442-23.29 35.137-23.29 9.696-41.108-8.282L271.029 702.696H144.92q-16.167 0-27.022-10.855-10.855-10.855-10.855-27.022V487.181q0-16.167 10.855-27.101 10.855-10.935 27.022-10.935h109.109L68.768 263.086q-10.225-10.224-9.892-24.703.334-14.478 10.558-24.702 10.225-10.225 24.53-10.225 14.304 0 24.528 10.225l714.697 718.175q10.224 10.224 10.224 24.702 0 14.478-10.224 24.544-10.225 10.384-25.076 10.384-14.852 0-25.076-10.384Zm-174.53-745.066q105.812 39.558 170.424 131.862Q843.543 460.203 843.543 575q0 52.464-14.525 101.942-14.525 49.478-42.511 93.21l-50.152-50.63q19-32.761 28.167-69.308 9.167-36.547 9.167-75.214 0-94.776-52.888-170.696-52.888-75.921-140.33-104.986-9.319-2.905-14.717-10.637-5.399-7.732-5.399-17.29 0-19.304 15.384-30.569 15.384-11.264 32.768-4.786ZM367.739 563.572Zm285.007 72.261-92.391-92.869V411.609q47.797 22.478 75.493 66.996 27.695 44.518 27.695 97.395 0 15.558-2.739 30.576t-8.058 29.257ZM480.355 462.406 369.5 350.674l46.457-46.457q17.818-17.819 41.108-8.044 23.29 9.776 23.29 34.899v131.334Zm-75.913 265.776V600.594l-75.217-75.536H182.797v101.884h120.406l101.239 101.24Z"/>
<path d="M770.974 963.435 663.179 855.64q-15.436 9.948-31.423 18.512-15.987 8.564-33.244 15-12.845 4.846-23.909-3.397-11.064-8.243-11.064-22.756 0-6.82 4.013-12.064 4.012-5.243 10.243-7.397 12.872-4.487 25.436-10.41t24-13.692L468.153 659.948v112.254q0 21.18-19.218 29.038-19.217 7.859-33.986-6.91L296.617 675.999H179.438q-13.564 0-22.423-8.859-8.859-8.859-8.859-22.423V507.283q0-13.564 8.859-22.423 8.859-8.859 22.423-8.859H283.54L94.155 286.36q-7.23-7.231-7.218-17.705.013-10.474 7.628-18.089 7.616-7.359 17.692-7.359 10.077 0 17.692 7.359l677.485 677.075q7.231 7.231 7.295 17.705.064 10.474-7.295 18.089-7.615 7.615-18.23 7.615t-18.23-7.615ZM598.512 260.591q97.769 38.231 157.551 123.423Q815.845 469.206 815.845 575q0 51.795-15.449 100.09t-44.398 90.217l-35.819-35.819q22.59-34.026 34-73.193Q765.59 617.129 765.59 575q0-91.743-51.308-165.628-51.308-73.885-136.487-103.321-6.82-2.153-10.538-7.692-3.718-5.538-3.718-12.358 0-14.051 11.269-22.025 11.269-7.974 23.704-3.385ZM376.257 568.718Zm257.28 74.129-69.998-69.999V427.847q40.461 22 62.538 61.961Q648.153 529.77 648.153 576q0 17.693-3.654 34.5-3.654 16.808-10.962 32.347ZM468.153 477.463l-86.306-86.692 33.102-33.101q14.769-14.769 33.986-6.782 19.218 7.987 19.218 28.653v97.922Zm-50.255 247.819V610.359l-84.103-84.103H198.411v99.488H318.36l99.538 99.538Z"/>
</svg>
)
}
@@ -3,7 +3,7 @@ import { CSSProperties } from "react";
export function VolumeUpIcon(props: {className?: string, style?: CSSProperties}) {
return (
<svg className={props.className} style={props.style} xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960" fill="currentColor">
<path d="M613.413 913.964q-18.051 6.478-33.101-5.08-15.051-11.558-15.051-31.434 0-9.558 5.326-17.044 5.326-7.485 14.551-10.55 86.775-32.08 140.116-106.747Q778.595 668.442 778.595 575q0-93.442-53.341-168.363-53.341-74.92-140.116-106.652-9.319-2.906-14.598-10.971t-5.279-17.623q0-19.304 15.384-30.569 15.384-11.264 32.768-4.786 105.812 39.558 170.304 131.862Q848.21 460.203 848.21 575t-64.493 207.102q-64.492 92.304-170.304 131.862ZM149.826 702.696q-16.326 0-27.181-10.855t-10.855-27.022V487.181q0-16.167 10.855-27.101 10.855-10.935 27.181-10.935h125.949l144.928-144.928q17.978-17.819 41.268-8.044 23.29 9.776 23.29 34.899v489.697q0 25.282-23.29 35.058-23.29 9.775-41.268-8.203L275.775 702.696H149.826Zm402.101 41.029V406.942q52.196 18.971 84.24 65.609Q668.21 519.188 668.21 576q0 57.478-32.043 103.036-32.044 45.558-84.24 64.689ZM409.348 427.818l-100.573 97.24H187.703v101.884h121.072l100.573 97.907V427.818ZM315.74 576Z"/>
<path d="M596.512 889.152q-12.846 4.846-23.91-3.416-11.063-8.263-11.063-22.794 0-6.763 4.012-12.007 4.013-5.243 10.244-7.397 84.769-32 136.282-104.936Q763.589 665.667 763.589 575t-51.512-163.808q-51.513-73.141-136.282-104.73-6.821-2.154-10.539-7.965-3.717-5.812-3.717-12.587 0-13.96 11.268-21.934 11.269-7.974 23.705-3.385 97.64 38.231 157.486 123.339 59.846 85.107 59.846 191.07t-59.846 191.07q-59.846 85.108-157.486 123.082ZM177.438 675.999q-13.468 0-22.375-8.907t-8.907-22.375V507.283q0-13.468 8.907-22.375t22.375-8.907h117.178L412.948 357.67q14.769-14.769 33.987-6.722 19.218 8.047 19.218 28.593v392.661q0 20.803-19.218 28.85t-33.987-6.722L294.616 675.999H177.438Zm374.357 49.949V424.463q43.051 19.102 68.704 60.551 25.654 41.448 25.654 90.986 0 50.205-25.654 90.525-25.653 40.32-68.704 59.423ZM415.898 429.436l-99.128 96.82H196.411v99.488H316.77l99.128 97.23V429.436ZM318.872 576Z"/>
</svg>
)
}
@@ -7,46 +7,46 @@ import { WindowManagerService } from 'renderer/services/window-manager.service';
import { AppWindow } from 'shared/models/window-manager/app-window.model';
import { BsmButton } from '../shared/bsm-button.component';
import { BsmRange } from '../shared/bsm-range.component';
import { BsmIcon, BsmIconType } from '../svgs/bsm-icon.component';
import { BsmIconType } from '../svgs/bsm-icon.component';
import './title-bar.component.css'
export default function TitleBar({template = "index.html"} : {template: AppWindow}) {
const ipcService = IpcService.getInstance();
const windows = WindowManagerService.getInstance();
const audio = AudioPlayerService.getInstance();
const ipcService = IpcService.getInstance();
const windows = WindowManagerService.getInstance();
const audio = AudioPlayerService.getInstance();
const volume = useObservable(audio.volume$);
const playing = useObservable(audio.playing$);
const color = useThemeColor("first-color");
const volume = useObservable(audio.volume$, audio.volume);
const playing = useObservable(audio.playing$);
const color = useThemeColor("first-color");
const [maximized, setMaximized] = useState(false);
const [maximized, setMaximized] = useState(false);
const closeWindow = () => {
return windows.close(template);
const closeWindow = () => {
return windows.close(template);
}
const maximizeWindow = () => {
ipcService.sendLazy('window.maximize');
}
const maximizeWindow = () => {
ipcService.sendLazy('window.maximize');
}
const minimizeWindow = () => {
ipcService.sendLazy('window.minimize');
}
const minimizeWindow = () => {
ipcService.sendLazy('window.minimize');
}
const resetWindow = () => {
ipcService.sendLazy('window.reset');
}
const resetWindow = () => {
ipcService.sendLazy('window.reset');
}
const toogleMaximize = () => {
if(maximized){ resetWindow(); }
else{ maximizeWindow(); }
setMaximized(!maximized);
}
const toogleMaximize = () => {
if(maximized){ resetWindow(); }
else{ maximizeWindow(); }
setMaximized(!maximized);
}
const volumeIcon: BsmIconType = (() => {
if(volume === 0){ return "volume-off"; }
if(volume < 0.5){ return "volume-down"; }
if(volume.muted || !volume.volume){ return "volume-off"; }
if(volume.volume < .5){ return "volume-down"; }
return "volume-up";
})()
@@ -60,11 +60,11 @@ export default function TitleBar({template = "index.html"} : {template: AppWindo
</div>
</div>
<div id="window-controls" className="h-full flex shrink-0 items-center">
<div className='h-full text-gray-800 dark:text-gray-200 mr-2 cursor-pointer flex flex-row justify-end items-center gap-2 group'>
<div className='h-full text-gray-800 dark:text-gray-200 pr-1 cursor-pointer flex flex-row justify-end items-center gap-2 group pl-5'>
<div className='shrink-0 w-0 overflow-hidden transition-all group-hover:w-16 group-hover:overflow-visible group-active:w-16 group-active:overflow-visible text-main-color-3'>
<BsmRange min={0} max={1} step={.01} values={[volume]} colors={[color, "currentColor"]} onChange={val => audio.setVolume(val[0])}/>
<BsmRange min={0} max={1} step={.01} values={[volume.muted ? 0 : volume.volume]} colors={[color, "currentColor"]} onChange={val => audio.setVolume(val[0])} onFinalChange={val => audio.setFinalVolume(val[0])}/>
</div>
<BsmButton className='shrink-0 h-[21px] w-[21px] aspect-square !bg-transparent flex items-start' icon={volumeIcon} withBar={false} onClick={() => audio.setVolume(0)}/>
<BsmButton className='shrink-0 h-[23px] w-[23px] aspect-square !bg-transparent flex items-start' iconClassName={volumeIcon === "volume-down" && "-translate-x-[1.8px]"} icon={volumeIcon} withBar={false} onClick={() => audio.toggleMute()}/>
</div>
<div onClick={minimizeWindow} className="text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-[#4F545C] cursor-pointer w-11 h-full shrink-0 flex justify-center items-center" id="min-button" >
<svg aria-hidden="false" width="12" height="12" viewBox="0 0 12 12"><rect fill="currentColor" width="10" height="1" x="1" y="6"> </rect></svg>
+48 -12
View File
@@ -1,5 +1,4 @@
import { Observable } from "rxjs";
import { BehaviorSubject } from "rxjs";
import { Observable, BehaviorSubject } from "rxjs";
import { ConfigurationService } from "./configuration.service";
export class AudioPlayerService{
@@ -18,24 +17,34 @@ export class AudioPlayerService{
private readonly _src$: BehaviorSubject<string> = new BehaviorSubject("");
private readonly _playing$: BehaviorSubject<boolean> = new BehaviorSubject(false);
private readonly _bpm$: BehaviorSubject<number> = new BehaviorSubject(0);
private readonly _volume$: BehaviorSubject<number> = new BehaviorSubject(0);
private readonly _volume$: BehaviorSubject<PlayerVolume>;
private lastVolume: number;
private constructor(){
this.config = ConfigurationService.getInstance();
console.log("BBB", this.config.get<PlayerVolume>("audio-level"));
this._volume$ = new BehaviorSubject(
this.config.get<PlayerVolume>("audio-level") || { volume: 0.5, muted: false }
);
this.lastVolume = this._volume$.value.volume;
this.player = new Audio();
this.player.onplay = () => this._playing$.next(true);
this.player.onpause = () => this._playing$.next(false);
this.player.onended = () => this._playing$.next(false);
this.player.onvolumechange = () => {
this._volume$.next(this.player.volume);
this.config.set("audio-level", this.player.volume, true);
}
this.player.volume = this.config.get("audio-level") ?? 0.5;
this._volume$.subscribe(volume => {
console.log("AAA", volume);
this.player.volume = volume.volume;
this.player.muted = volume.muted;
this.config.set("audio-level", volume);
});
}
public play(src: string, bpm = 0): Promise<void>{
@@ -56,7 +65,28 @@ export class AudioPlayerService{
}
public setVolume(volume: number): void{
this.player.volume = volume;
const playerVolume: PlayerVolume = {muted: volume <= 0, volume};
this._volume$.next(playerVolume);
}
public setFinalVolume(volume: number): void{
if(volume > 0){ this.lastVolume = volume; }
const playerVolume: PlayerVolume = {muted: volume <= 0, volume: this.lastVolume};
this._volume$.next(playerVolume);
}
public mute(): void{
const playerVolume = {...this._volume$.value, muted: true};
this._volume$.next(playerVolume);
}
public unmute(): void{
const playerVolume = {...this._volume$.value, muted: false};
this._volume$.next(playerVolume);
}
public toggleMute(): void{
this.muted ? this.unmute() : this.mute();
}
public get src$(): Observable<string>{
@@ -68,13 +98,19 @@ export class AudioPlayerService{
public get bpm$(): Observable<number>{
return this._bpm$.asObservable();
}
public get volume$(): Observable<number>{
public get volume$(): Observable<PlayerVolume>{
return this._volume$.asObservable();
}
public get src(): string{ return this._src$.value; }
public get playing(): boolean{ return this._playing$.value; }
public get bpm(): number{ return this._bpm$.value; }
public get volume(): number{ return this._volume$.value; }
public get volume(): PlayerVolume{ return this._volume$.value; }
public get muted(): boolean{ return this.player.muted; }
}
interface PlayerVolume{
volume: number;
muted: boolean;
}