Skip to content

Commit

Permalink
Merge pull request #181 from iceljc/features/refine-chat-window
Browse files Browse the repository at this point in the history
Features/refine chat window
  • Loading branch information
iceljc authored Aug 5, 2024
2 parents 713a3a8 + 4cd74f6 commit d17d1bd
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 17 deletions.
5 changes: 4 additions & 1 deletion src/lib/common/AudioGallery.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
/** @type {import('$types').AudioFileModel[]} */
export let audios = [];
/** @type {string} */
export let id;
/** @type {string} */
export let containerClasses = "";
Expand All @@ -20,6 +23,6 @@
class="{disableDefaultStyles ? '' : 'audio-gallery-list'} {containerClasses}"
style={`${containerStyles}`}
>
<AudioPlayer audio={audios} />
<AudioPlayer id={id} audio={audios} />
</div>
{/if}
4 changes: 4 additions & 0 deletions src/lib/common/MessageFileGallery.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
/** @type {string} */
export let galleryStyles = '';
/** @type {string} */
export let messageId;
/** @type {() => Promise<any>} */
export let fetchFiles = () => Promise.resolve([]);
Expand Down Expand Up @@ -56,6 +59,7 @@
files={textFiles}
/>
<AudioGallery
id={messageId}
containerClasses={galleryClasses}
containerStyles={galleryStyles}
audios={audioFiles}
Expand Down
7 changes: 6 additions & 1 deletion src/lib/common/audio-player/AudioPlayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {
initPlayer,
stopAll,
clearAudioInstantce,
useAudioStore
} from "./store";
import { volumeEventHandlers, progressEventHandlers } from "./handlers";
Expand Down Expand Up @@ -46,6 +47,9 @@
/** @type {import('$types').AudioFileModel[]} */
export let audio;
/** @type {string} */
export let id;
/** @type {"list" | "random"} */
export let order = 'list';
Expand Down Expand Up @@ -182,11 +186,12 @@
onDestroy(() => {
dispatch("destroy");
clearAudioInstantce(id);
});
const init = () => {
const audioPlayer = document.createElement("audio");
initPlayer(audioPlayer, dispatch);
initPlayer({ id: id, player: audioPlayer }, dispatch);
isShowList = !propsBool($$props, "list_folded") && $audioList.length > 1;
volume = Math.max(volume, 0);
volume = Math.min(volume, 1);
Expand Down
21 changes: 17 additions & 4 deletions src/lib/common/audio-player/AudioSpeaker.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<script>
import { initSpeech, stopAll } from "$lib/common/audio-player/store";
import { onMount } from "svelte";
import { initSpeech, stopAll, clearSpeakerInstantce } from "$lib/common/audio-player/store";
import { onMount, onDestroy } from "svelte";
/** @type {string} */
export let text;
/** @type {string} */
export let id;
/** @type {boolean} */
export let mutex = true;
Expand All @@ -30,9 +33,11 @@
utterThis.onend = (e) => { stop(); };
speech = {
id: id,
synth: window?.speechSynthesis,
utterThis: utterThis,
stop: () => stop()
stop: () => stop(),
isSpeaking: () => isSpeaking()
};
initSpeech(speech);
});
Expand All @@ -59,10 +64,18 @@
const stop = () => {
speaking = false;
if (speech?.synth) {
if (speech?.synth && speech.synth.speaking) {
speech.synth.cancel();
}
}
const isSpeaking = () => {
return speaking;
}
onDestroy(() => {
clearSpeakerInstantce(id);
});
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
Expand Down
38 changes: 30 additions & 8 deletions src/lib/common/audio-player/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import { derived, writable } from "svelte/store";
import { secondToTime } from "./utils";
import { SPEECH_VOICES } from "$lib/services/web-speech";

/** @type {HTMLAudioElement[]} */
export const instances = [];
/** @type {import('$types').AudioModel[]} */
export const audioInstances = [];

/** @type {import('$types').SpeechModel[]} */
export const speechInstances = [];

/**
* @param {HTMLAudioElement} player
* @param {import('$types').AudioModel} audio
* @param {(name: string, detail?: any) => void} dispatch
*/
export function initPlayer(player, dispatch) {
instances.push(player);
bindAudioEvent(player, dispatch);
export function initPlayer(audio, dispatch) {
audioInstances.push(audio);
bindAudioEvent(audio.player, dispatch);
}

/** @param {import('$types').SpeechModel} speech */
Expand All @@ -26,9 +26,31 @@ export function initSpeech(speech) {
speechInstances.push(speech);
}

/** @param {string} id */
export function clearAudioInstantce(id) {
const foundIdx = audioInstances.findIndex(x => x.id === id);
if (foundIdx > -1) {
if (!audioInstances[foundIdx].player?.paused) {
audioInstances[foundIdx].player?.pause();
}
audioInstances.splice(foundIdx, 1);
}
}

/** @param {string} id */
export function clearSpeakerInstantce(id) {
const foundIdx = speechInstances.findIndex(x => x.id === id);
if (foundIdx > -1) {
if (speechInstances[foundIdx].isSpeaking()) {
speechInstances[foundIdx].stop();
}
speechInstances.splice(foundIdx, 1);
}
}

export function stopAll() {
if (instances?.length > 0) {
instances.forEach(player => player.pause());
if (audioInstances?.length > 0) {
audioInstances.forEach(audio => audio.player?.pause());
}
if (speechInstances?.length > 0) {
speechInstances.forEach(sp => sp.stop());
Expand Down
9 changes: 8 additions & 1 deletion src/lib/helpers/types/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,17 @@
// Speech
/**
* @typedef {Object} SpeechModel
* @property {string} [id]
* @property {string} id
* @property {SpeechSynthesis} synth
* @property {SpeechSynthesisUtterance} utterThis
* @property {() => void} stop
* @property {() => boolean} isSpeaking
*/

/**
* @typedef {Object} AudioModel
* @property {string} id
* @property {HTMLAudioElement} player
*/


Expand Down
1 change: 1 addition & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
let isLoading;
onMount(() => {
window?.speechSynthesis?.cancel();
const subscribe = loaderStore.subscribe(value => {
isLoading = value;
});
Expand Down
9 changes: 7 additions & 2 deletions src/routes/chat/[agentId]/[conversationId]/chat-box.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@
* @param {any[]} files
*/
function buildFilePayload(files) {
if (!files) return '';
if (!files || files.length === 0) return '';
const excelCount = files.filter(x => isExcel(x.file_type || x.file_name)).length;
const pdfCount = files.filter(x => isPdf(x.file_type || x.file_name)).length;
Expand Down Expand Up @@ -1084,6 +1084,7 @@
{/if}
{#if !!message.is_chat_message || !!message.has_message_files}
<MessageFileGallery
messageId={message?.message_id}
galleryStyles={'justify-content: flex-end;'}
fetchFiles={() => getConversationFiles(params.conversationId, message.message_id, FileSourceType.User)}
/>
Expand Down Expand Up @@ -1111,9 +1112,13 @@
</div>
<div class="msg-container">
<RcMessage message={message} />
<AudioSpeaker text={message?.rich_content?.message?.text || message?.text} />
<AudioSpeaker
id={message?.message_id}
text={message?.rich_content?.message?.text || message?.text}
/>
{#if !!message.is_chat_message || !!message.has_message_files}
<MessageFileGallery
messageId={message?.message_id}
galleryStyles={'justify-content: flex-start;'}
fetchFiles={() => getConversationFiles(params.conversationId, message.message_id, FileSourceType.Bot)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
</p>
{#if !!dialog.has_message_files}
<MessageFileGallery
messageId={dialog?.message_id}
galleryClasses={'dialog-file-display'}
fetchFiles={() => getConversationFiles(conversation.id, dialog.message_id, showInRight(dialog) ? FileSourceType.User : FileSourceType.Bot)}
/>
Expand Down

0 comments on commit d17d1bd

Please sign in to comment.