Skip to content

Commit

Permalink
feat: add music (#18)
Browse files Browse the repository at this point in the history
* chore: Add music

* chore: add service

* chore: add more data music

* fix: cspell

* chore: Add musics

* chore: change music data

* fix: fix cspell

* fix: remove Nan length

* chore: add buttons music

* chore: change music service

* chore: change heading

* chore: remove invisible

* chore: remove extra code

* chore: rename functions

* chore: add (ended) event

* chore: rename more functions

* chore: remove extra code

* fix: play next music
  • Loading branch information
MishaZhem authored Jul 31, 2024
1 parent 60e8302 commit 7325c63
Show file tree
Hide file tree
Showing 12 changed files with 251 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"heatindex",
"forecastday",
"mintemp",
"maxtemp"
"maxtemp",
"Tiko"
]
}
Binary file not shown.
Binary file not shown.
Binary file added apps/taiga-lumbermill/public/music/against.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/taiga-lumbermill/public/music/howling.avif
Binary file not shown.
Binary file added apps/taiga-lumbermill/public/music_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<div
tuiAppearance="whiteblock"
tuiCardLarge="normal"
class="card"
>
<header tuiHeader>
<h2
tuiTitle
[style.text-align]="'center'"
>
Music
</h2>
</header>
<div class="info">
<img
class="logo"
[src]="tracks[activeIndex].logo"
/>
<h2 class="tui-space_top-4 tui-space_bottom-2">
{{ tracks[activeIndex].name }}
</h2>
<p
class="tui-space_top-0 tui-space_bottom-0"
[style.color]="'var(--tui-text-primary)'"
>
{{ tracks[activeIndex].performer }}
</p>
</div>
<audio
#audio
tuiMedia
[src]="tracks[activeIndex].src"
[(currentTime)]="time"
[(paused)]="paused"
[(volume)]="volume"
(ended)="nextTrack(audio)"
></audio>
<div>
<input
size="m"
tuiSlider
type="range"
[max]="audio.duration"
[(ngModel)]="time"
/>
<div class="duration">
<p class="tui-space_top-0 tui-space_bottom-0">{{ getMinutes(time) }}:{{ getSeconds(time) }}</p>
<p class="tui-space_top-0 tui-space_bottom-0">
{{ getMinutes(tracks[activeIndex].length) }}:{{ getSeconds(tracks[activeIndex].length) }}
</p>
</div>
</div>
<div class="buttons">
<button
appearance="icon"
iconStart="@tui.shuffle"
tuiIconButton
[tuiAppearanceState]="shuffle ? 'active' : null"
(click)="shuffle = !shuffle"
></button>
<button
appearance="icon"
iconStart="@tui.skip-back"
tuiIconButton
(click)="previousTrack(audio)"
></button>
<button
appearance="icon"
tuiIconButton
[iconStart]="this.paused ? '@tui.circle-play' : '@tui.circle-stop'"
(click)="paused = !paused"
></button>
<button
appearance="icon"
iconStart="@tui.skip-forward"
tuiIconButton
(click)="nextTrack(audio)"
></button>
<button
appearance="icon"
iconStart="@tui.repeat"
tuiIconButton
[tuiAppearanceState]="repeat ? 'active' : null"
(click)="repeat = !repeat"
></button>
</div>
<hr />
<div class="volume">
<tui-icon icon="@tui.volume-1" />
<input
max="1"
size="m"
step="0.01"
tuiSlider
type="range"
[style.color]="'var(--tui-status-info)'"
[(ngModel)]="volume"
/>
<tui-icon icon="@tui.volume-2" />
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@import '@taiga-ui/core/styles/taiga-ui-local.less';

.duration {
display: flex;
justify-content: space-between;
color: var(--tui-text-primary);
}

.buttons {
display: flex;
align-items: center;
justify-content: space-around;
}

.volume {
display: flex;
align-items: center;
gap: 0.5rem;
}

.info {
display: flex;
flex-direction: column;
align-items: center;
}

.logo {
border-radius: 0.5rem;
width: 9rem;
height: 9rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {CommonModule} from '@angular/common';
import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {TuiMedia} from '@taiga-ui/cdk';
import {TuiAppearance, TuiButton, TuiIcon} from '@taiga-ui/core';
import {TuiSliderComponent} from '@taiga-ui/kit';
import {TuiCardLarge} from '@taiga-ui/layout';

import {getRandomInt, MusicService} from './music.service';

@Component({
standalone: true,
selector: 'lmb-music',
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
TuiAppearance,
TuiButton,
TuiCardLarge,
TuiIcon,
TuiMedia,
TuiSliderComponent,
],
templateUrl: './music.component.html',
styleUrl: './music.component.less',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MusicComponent {
protected tracks = inject(MusicService).tracks;
protected activeIndex = 0;
protected time = 0;
protected volume = 1;
protected repeat = false;
protected shuffle = false;
protected paused = true;

protected nextTrack(audio: HTMLAudioElement): void {
this.time = 0;

if (this.repeat) {
return;
}

this.activeIndex = this.shuffle
? getRandomInt(this.tracks.length)
: (this.activeIndex + 1) % this.tracks.length;

setTimeout(async () => audio.play(), 1);
}

protected previousTrack(audio: HTMLAudioElement): void {
this.time = 0;

if (this.repeat) {
return;
}

const nextItem =
this.activeIndex - 1 < 0 ? this.tracks.length - 1 : this.activeIndex - 1;

this.activeIndex = this.shuffle ? getRandomInt(this.tracks.length) : nextItem;
setTimeout(async () => audio.play(), 1);
}

protected getMinutes(value: number): string {
return (value / 60 <= 9 ? '0' : '') + Math.trunc(value / 60).toString();
}

protected getSeconds(value: number): string {
value = Math.trunc(value);

return (value % 60 <= 9 ? '0' : '') + (value % 60).toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {Injectable} from '@angular/core';

interface Track {
readonly name: string;
readonly src: string;
readonly length: number;
readonly logo: string;
readonly performer: string;
}

export const INITIAL_DATA: Track[] = [
{
name: 'Against All Odds',
logo: '/music/against.jpg',
performer: 'Tiko Tiko',
src: './music/AgainstAllOdds.mp3',
length: 208,
},
{
name: 'Howling at the Moon',
logo: '/music/howling.avif',
performer: 'D Fine Us',
src: './music/HowlingAtTheMoon.mp3',
length: 195,
},
];

@Injectable({
providedIn: 'root',
})
export class MusicService {
public readonly tracks = INITIAL_DATA;
}

export function getRandomInt(max: number): number {
return Math.floor(Math.random() * max);
}
4 changes: 3 additions & 1 deletion apps/taiga-lumbermill/src/dashboards/iot/iot.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
<div class="grow">
<lmb-weather />
</div>
<div class="grow"></div>
<div class="grow">
<lmb-music />
</div>
<div class="grow">
<lmb-contacts />
</div>
Expand Down
2 changes: 2 additions & 0 deletions apps/taiga-lumbermill/src/dashboards/iot/iot.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {ControlPanelComponent} from './components/control-panel/control-panel.co
import {CostComponent} from './components/Cost/cost.component';
import {ElectricityComponent} from './components/electricity/electricity.component';
import {LightingComponent} from './components/Lighting/lighting.component';
import {MusicComponent} from './components/music/music.component';
import {SafetyComponent} from './components/Safety/safety.component';
import {WeatherComponent} from './components/weather/weather.component';

Expand All @@ -25,6 +26,7 @@ import {WeatherComponent} from './components/weather/weather.component';
CostComponent,
ElectricityComponent,
LightingComponent,
MusicComponent,
SafetyComponent,
TuiAppearance,
TuiCardLarge,
Expand Down

0 comments on commit 7325c63

Please sign in to comment.