Skip to content

Commit cef134b

Browse files
committed
[Feature - Inline Audio Message] - Mini audio player added if message is audio.
1 parent 71ffeee commit cef134b

3 files changed

Lines changed: 203 additions & 2 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
@keyframes quiet {
2+
25%{
3+
transform: scaleY(.6);
4+
}
5+
50%{
6+
transform: scaleY(.4);
7+
}
8+
75%{
9+
transform: scaleY(.8);
10+
}
11+
}
12+
13+
@keyframes normal {
14+
25%{
15+
transform: scaleY(1);
16+
}
17+
50%{
18+
transform: scaleY(.4);
19+
}
20+
75%{
21+
transform: scaleY(.6);
22+
}
23+
}
24+
@keyframes loud {
25+
25%{
26+
transform: scaleY(1);
27+
}
28+
50%{
29+
transform: scaleY(.4);
30+
}
31+
75%{
32+
transform: scaleY(1.2);
33+
}
34+
}
35+
36+
.audio-message-container {
37+
display: flex;
38+
flex-direction: column;
39+
}
40+
41+
.audio-message-metadata {
42+
color: var(--color-text);
43+
font-size: 0.8rem;
44+
}
45+
46+
.audio-message-btn {
47+
height: 24px
48+
}
49+
50+
.audio-message {
51+
display: flex;
52+
justify-content: space-between;
53+
align-items: center;
54+
}
55+
56+
.sound-bar-container{
57+
display: flex;
58+
justify-content: space-between;
59+
height: 32px;
60+
--boxSize: 4px;
61+
--gutter: 2px;
62+
width: calc((var(--boxSize) + var(--gutter)) * 12);
63+
margin-left: 6px;
64+
}
65+
66+
.sound-bar {
67+
height: 100%;
68+
width: var(--boxSize);
69+
background: #0099cc;
70+
border-radius: 2px;
71+
}
72+
73+
.sound-bar-animate {
74+
animation-duration: 1.2s;
75+
animation-timing-function: ease-in-out;
76+
animation-iteration-count: infinite;
77+
}
78+
79+
.sound-bar-0{
80+
transform: scaleY(.3);
81+
animation-name: quiet;
82+
}
83+
84+
.sound-bar-1{
85+
transform: scaleY(.6);
86+
animation-name: normal;
87+
}
88+
89+
.sound-bar-2{
90+
transform: scaleY(.3);
91+
animation-name: quiet;
92+
}
93+
94+
.sound-bar-3{
95+
transform: scaleY(.8);
96+
animation-name: loud;
97+
}
98+
99+
.sound-bar-4{
100+
transform: scaleY(.3);
101+
animation-name: quiet;
102+
}
103+
104+
.sound-bar-5{
105+
transform: scaleY(.6);
106+
animation-name: normal;
107+
}
108+
109+
.sound-bar-6{
110+
transform: scaleY(.3);
111+
animation-name: quiet;
112+
}
113+
114+
.sound-bar-7{
115+
transform: scaleY(.8);
116+
animation-name: loud;
117+
}
118+
119+
.sound-bar-8{
120+
transform: scaleY(.3);
121+
animation-name: quiet;
122+
}
123+
124+
.sound-bar-9{
125+
transform: scaleY(.6);
126+
animation-name: normal;
127+
}
128+
129+
.sound-bar-10{
130+
transform: scaleY(.3);
131+
animation-name: quiet;
132+
}

app/helpers/messages/attachment_presentation.rb

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ def initialize(message, context:)
55

66
def render
77
if message.attachment.attached?
8-
if message.attachment.previewable? || message.attachment.variable?
8+
if message.attachment.previewable? || message.attachment.variable? || message.attachment.audio?
99
render_preview
1010
else
1111
render_link
@@ -20,6 +20,8 @@ def render
2020
def render_preview
2121
if message.attachment.video?
2222
video_preview_tag
23+
elsif message.attachment.audio?
24+
audio_preview_tag
2325
else
2426
lightboxed_image_preview_tag
2527
end
@@ -35,6 +37,30 @@ def video_preview_tag
3537
end
3638
end
3739

40+
def audio_preview_tag
41+
tag.div class: "audio-message-container", data: { controller: "sound", sound_url_value: rails_blob_path(message.attachment), sound_audio_message_duration_value: message.attachment.metadata["duration"].to_i } do
42+
tag.div class: "sound audio-message" do
43+
tag.button("🔊", class: "btn btn--plain audio-message-btn", data: { action: "sound#playAndAnimate" }) + sound_preview_tag
44+
end + tag.div(message.attachment.metadata["duration"].to_i, class: "audio-message-metadata", data: { sound_target: "audioMessageMetadata" })
45+
end
46+
end
47+
48+
def generate_sound_bars_tags
49+
html_element = ""
50+
51+
11.times do |i|
52+
html_element << tag.div(class: "sound-bar sound-bar-#{i}")
53+
end
54+
55+
html_element.html_safe
56+
end
57+
58+
def sound_preview_tag
59+
tag.div(class: "sound-bar-container", data: { sound_target: "soundBarContainer" }) do
60+
generate_sound_bars_tags
61+
end
62+
end
63+
3864
def lightboxed_image_preview_tag
3965
width, height = preview_dimensions
4066

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,53 @@
11
import { Controller } from "@hotwired/stimulus"
22

33
export default class extends Controller {
4-
static values = { "url": String }
4+
static values = { "url": String, "audioMessageDuration": Number }
5+
static targets = [ "soundBarContainer", "audioMessageMetadata" ]
6+
7+
audioMessageMetadataTargetConnected() {
8+
this.#setInitialDurationMetadata();
9+
}
510

611
play() {
712
const sound = new Audio(this.urlValue)
813
sound.play()
914
}
15+
16+
playAndAnimate() {
17+
const sound = new Audio(this.urlValue)
18+
sound.addEventListener("ended", () => {
19+
this.#removeSoundBarAnimateCss();
20+
this.#setInitialDurationMetadata();
21+
});
22+
23+
sound.addEventListener("timeupdate", (event) => {
24+
this.audioMessageMetadataTarget.innerHTML = this.#formatTime(this.audioMessageDurationValue - sound.currentTime)
25+
});
26+
27+
sound.play()
28+
this.#addSoundBarAnimateCss()
29+
}
30+
31+
#removeSoundBarAnimateCss () {
32+
for (const soundBarItem of this.soundBarContainerTarget.children) {
33+
soundBarItem.classList.remove("sound-bar-animate")
34+
}
35+
}
36+
37+
#addSoundBarAnimateCss() {
38+
for (const soundBarItem of this.soundBarContainerTarget.children) {
39+
soundBarItem.classList.add("sound-bar-animate")
40+
}
41+
}
42+
43+
#formatTime(timeInSeconds) {
44+
let minutes = Math.floor(Math.ceil(timeInSeconds) / 60)
45+
let seconds = Math.ceil(timeInSeconds) % 60
46+
47+
return (minutes < 10 ? '0' + minutes : minutes) + ":" + (seconds < 10 ? '0' + seconds : seconds)
48+
}
49+
50+
#setInitialDurationMetadata() {
51+
this.audioMessageMetadataTarget.innerHTML = this.#formatTime(this.audioMessageDurationValue)
52+
}
1053
}

0 commit comments

Comments
 (0)