Support sending clap events at a specific time in audio mode

This commit is contained in:
N-Pex 2023-06-07 09:39:05 +02:00
parent 5f3f5d0afd
commit d5182395af
9 changed files with 149 additions and 21 deletions

View file

@ -14,6 +14,7 @@ export default {
constructor() {
this.player = new Audio();
this.currentEvent = null;
this.currentClapReactions = [];
this.infoMap = new Map();
this.player.addEventListener("durationchange", this.onDurationChange.bind(this));
this.player.addEventListener("timeupdate", this.onTimeUpdate.bind(this));
@ -70,15 +71,15 @@ export default {
);
}
play(event) {
this.play_(event, false);
play(event, timelineSet) {
this.play_(event, timelineSet, false);
}
load(event) {
this.play_(event, true);
load(event, timelineSet) {
this.play_(event, timelineSet, true);
}
play_(event, onlyLoad) {
play_(event, timelineSet, onlyLoad) {
const eventId = event.getId();
if (this.currentEvent != eventId) {
// Media change, pause the one currently playing.
@ -91,6 +92,10 @@ export default {
this.currentEvent = eventId;
const info = this.infoMap.get(eventId);
if (info) {
// Get all clap reactions
this.initializeClapEvents(event, timelineSet);
if (info.url) {
// Restart from beginning?
if (info.currentTime == info.duration) {
@ -121,9 +126,9 @@ export default {
// Still on this item? Call ourselves recursively.
if (this.currentEvent == eventId) {
if (onlyLoad) {
this.load(event);
this.load(event, timelineSet);
} else {
this.play(event);
this.play(event, timelineSet);
}
}
})
@ -204,8 +209,10 @@ export default {
onTimeUpdate() {
var entry = this.infoMap.get(this.currentEvent);
if (entry) {
const oldTime = entry.currentTime;
entry.currentTime = 1000 * this.player.currentTime;
this.updatePlayPercent(entry);
this.maybePlayClapEvent(oldTime, entry.currentTime);
}
}
onDurationChange() {
@ -226,6 +233,34 @@ export default {
entry.playPercent = 0;
}
}
initializeClapEvents(event, timelineSet) {
if (event) {
const reactions = timelineSet.relations.getChildEventsForEvent(event.getId(), 'm.annotation', 'm.reaction');
if (reactions) {
this.currentClapReactions = reactions.getRelations()
.filter(r => r.getRelation().key == "👏" && r.getRelation().timeOffset && parseInt(r.getRelation().timeOffset) > 0)
.map(r => {
return {
sender: r.getSender(),
emoji: r.getRelation().key,
timeOffset: parseInt(r.getRelation().timeOffset)
}
})
.sort((a,b) => a.timeOffset - b.timeOffset);
}
} else {
this.currentClapReactions = [];
}
}
maybePlayClapEvent(previousTimeMs, timeNowMs) {
(this.currentClapReactions || []).forEach(reaction => {
if (previousTimeMs < reaction.timeOffset && timeNowMs >= reaction.timeOffset) {
this.$root.$emit("audio-playback-reaction", reaction);
}
});
}
}
Vue.prototype.$audioPlayer = new SharedAudioPlayer();