refac: styling
This commit is contained in:
@@ -1651,56 +1651,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="self-end flex space-x-1 mr-1 shrink-0 gap-[0.5px]">
|
<div class="self-end flex space-x-1 mr-1 shrink-0 gap-[0.5px]">
|
||||||
{#if (!history?.currentId || history.messages[history.currentId]?.done == true) && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.stt ?? true))}
|
|
||||||
<!-- {$i18n.t('Record voice')} -->
|
|
||||||
<Tooltip content={$i18n.t('Dictate')}>
|
|
||||||
<button
|
|
||||||
id="voice-input-button"
|
|
||||||
class=" text-gray-600 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200 transition rounded-full p-1.5 self-center"
|
|
||||||
type="button"
|
|
||||||
on:click={async () => {
|
|
||||||
try {
|
|
||||||
let stream = await navigator.mediaDevices
|
|
||||||
.getUserMedia({ audio: true })
|
|
||||||
.catch(function (err) {
|
|
||||||
toast.error(
|
|
||||||
$i18n.t(
|
|
||||||
`Permission denied when accessing microphone: {{error}}`,
|
|
||||||
{
|
|
||||||
error: err
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (stream) {
|
|
||||||
recording = true;
|
|
||||||
const tracks = stream.getTracks();
|
|
||||||
tracks.forEach((track) => track.stop());
|
|
||||||
}
|
|
||||||
stream = null;
|
|
||||||
} catch {
|
|
||||||
toast.error($i18n.t('Permission denied when accessing microphone'));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
aria-label="Voice Input"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
class="w-5 h-5 translate-y-[0.5px]"
|
|
||||||
>
|
|
||||||
<path d="M7 4a3 3 0 016 0v6a3 3 0 11-6 0V4z" />
|
|
||||||
<path
|
|
||||||
d="M5.5 9.643a.75.75 0 00-1.5 0V10c0 3.06 2.29 5.585 5.25 5.954V17.5h-1.5a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-1.5v-1.546A6.001 6.001 0 0016 10v-.357a.75.75 0 00-1.5 0V10a4.5 4.5 0 01-9 0v-.357z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if (taskIds && taskIds.length > 0) || (history.currentId && history.messages[history.currentId]?.done != true) || generating}
|
{#if (taskIds && taskIds.length > 0) || (history.currentId && history.messages[history.currentId]?.done != true) || generating}
|
||||||
<div class=" flex items-center">
|
<div class=" flex items-center">
|
||||||
<Tooltip content={$i18n.t('Stop')}>
|
<Tooltip content={$i18n.t('Stop')}>
|
||||||
@@ -1725,113 +1675,166 @@
|
|||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
{:else if prompt === '' && files.length === 0 && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.call ?? true))}
|
{:else}
|
||||||
<div class=" flex items-center">
|
{#if prompt !== '' && ($config?.features?.enable_notes ?? false) && ($user?.role === 'admin' || ($user?.permissions?.features?.notes ?? true))}
|
||||||
<!-- {$i18n.t('Call')} -->
|
<Tooltip
|
||||||
<Tooltip content={$i18n.t('Voice mode')}>
|
content={$i18n.t('Create note')}
|
||||||
|
className="-mr-[0.5px] flex items-center"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
class=" bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full p-1.5 self-center"
|
id="send-message-button"
|
||||||
|
class=" text-gray-600 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200 transition rounded-full p-1.5 self-center"
|
||||||
|
type="button"
|
||||||
|
disabled={prompt === '' && files.length === 0}
|
||||||
|
on:click={() => {
|
||||||
|
createNote();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PageEdit className="size-4.5 translate-y-[0.5px]" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if (!history?.currentId || history.messages[history.currentId]?.done == true) && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.stt ?? true))}
|
||||||
|
<!-- {$i18n.t('Record voice')} -->
|
||||||
|
<Tooltip content={$i18n.t('Dictate')}>
|
||||||
|
<button
|
||||||
|
id="voice-input-button"
|
||||||
|
class=" text-gray-600 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200 transition rounded-full p-1.5 self-center mr-0.5"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
if (selectedModels.length > 1) {
|
|
||||||
toast.error($i18n.t('Select only one model to call'));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($config.audio.stt.engine === 'web') {
|
|
||||||
toast.error(
|
|
||||||
$i18n.t('Call feature is not supported when using Web STT engine')
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check if user has access to getUserMedia
|
|
||||||
try {
|
try {
|
||||||
let stream = await navigator.mediaDevices.getUserMedia({
|
let stream = await navigator.mediaDevices
|
||||||
audio: true
|
.getUserMedia({ audio: true })
|
||||||
});
|
.catch(function (err) {
|
||||||
// If the user grants the permission, proceed to show the call overlay
|
toast.error(
|
||||||
|
$i18n.t(
|
||||||
|
`Permission denied when accessing microphone: {{error}}`,
|
||||||
|
{
|
||||||
|
error: err
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
if (stream) {
|
if (stream) {
|
||||||
|
recording = true;
|
||||||
const tracks = stream.getTracks();
|
const tracks = stream.getTracks();
|
||||||
tracks.forEach((track) => track.stop());
|
tracks.forEach((track) => track.stop());
|
||||||
}
|
}
|
||||||
|
|
||||||
stream = null;
|
stream = null;
|
||||||
|
} catch {
|
||||||
if ($settings.audio?.tts?.engine === 'browser-kokoro') {
|
toast.error($i18n.t('Permission denied when accessing microphone'));
|
||||||
// If the user has not initialized the TTS worker, initialize it
|
|
||||||
if (!$TTSWorker) {
|
|
||||||
await TTSWorker.set(
|
|
||||||
new KokoroWorker({
|
|
||||||
dtype: $settings.audio?.tts?.engineConfig?.dtype ?? 'fp32'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
await $TTSWorker.init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showCallOverlay.set(true);
|
|
||||||
showControls.set(true);
|
|
||||||
} catch (err) {
|
|
||||||
// If the user denies the permission or an error occurs, show an error message
|
|
||||||
toast.error(
|
|
||||||
$i18n.t('Permission denied when accessing media devices')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
aria-label={$i18n.t('Voice mode')}
|
aria-label="Voice Input"
|
||||||
>
|
|
||||||
<Voice className="size-5" strokeWidth="2.5" />
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
{#if ($config?.features?.enable_notes ?? false) && ($user?.role === 'admin' || ($user?.permissions?.features?.notes ?? true))}
|
|
||||||
<div class=" flex items-center">
|
|
||||||
<Tooltip content={$i18n.t('Create note')}>
|
|
||||||
<button
|
|
||||||
id="send-message-button"
|
|
||||||
class=" text-gray-600 mr-0.5 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200 transition rounded-full p-1.5 self-center"
|
|
||||||
type="button"
|
|
||||||
disabled={prompt === '' && files.length === 0}
|
|
||||||
on:click={() => {
|
|
||||||
createNote();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PageEdit className="size-5" />
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class=" flex items-center">
|
|
||||||
<Tooltip content={$i18n.t('Send message')}>
|
|
||||||
<button
|
|
||||||
id="send-message-button"
|
|
||||||
class="{!(prompt === '' && files.length === 0)
|
|
||||||
? 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
|
|
||||||
: 'text-white bg-gray-200 dark:text-gray-900 dark:bg-gray-700 disabled'} transition rounded-full p-1.5 self-center"
|
|
||||||
type="submit"
|
|
||||||
disabled={prompt === '' && files.length === 0}
|
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 20 20"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="size-5"
|
class="size-5 translate-y-[0.5px]"
|
||||||
>
|
>
|
||||||
|
<path d="M7 4a3 3 0 016 0v6a3 3 0 11-6 0V4z" />
|
||||||
<path
|
<path
|
||||||
fill-rule="evenodd"
|
d="M5.5 9.643a.75.75 0 00-1.5 0V10c0 3.06 2.29 5.585 5.25 5.954V17.5h-1.5a.75.75 0 000 1.5h4.5a.75.75 0 000-1.5h-1.5v-1.546A6.001 6.001 0 0016 10v-.357a.75.75 0 00-1.5 0V10a4.5 4.5 0 01-9 0v-.357z"
|
||||||
d="M8 14a.75.75 0 0 1-.75-.75V4.56L4.03 7.78a.75.75 0 0 1-1.06-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1-1.06 1.06L8.75 4.56v8.69A.75.75 0 0 1 8 14Z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
|
{#if prompt === '' && files.length === 0 && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.call ?? true))}
|
||||||
|
<div class=" flex items-center">
|
||||||
|
<!-- {$i18n.t('Call')} -->
|
||||||
|
<Tooltip content={$i18n.t('Voice mode')}>
|
||||||
|
<button
|
||||||
|
class=" bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full p-1.5 self-center"
|
||||||
|
type="button"
|
||||||
|
on:click={async () => {
|
||||||
|
if (selectedModels.length > 1) {
|
||||||
|
toast.error($i18n.t('Select only one model to call'));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($config.audio.stt.engine === 'web') {
|
||||||
|
toast.error(
|
||||||
|
$i18n.t('Call feature is not supported when using Web STT engine')
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// check if user has access to getUserMedia
|
||||||
|
try {
|
||||||
|
let stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
audio: true
|
||||||
|
});
|
||||||
|
// If the user grants the permission, proceed to show the call overlay
|
||||||
|
|
||||||
|
if (stream) {
|
||||||
|
const tracks = stream.getTracks();
|
||||||
|
tracks.forEach((track) => track.stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = null;
|
||||||
|
|
||||||
|
if ($settings.audio?.tts?.engine === 'browser-kokoro') {
|
||||||
|
// If the user has not initialized the TTS worker, initialize it
|
||||||
|
if (!$TTSWorker) {
|
||||||
|
await TTSWorker.set(
|
||||||
|
new KokoroWorker({
|
||||||
|
dtype: $settings.audio?.tts?.engineConfig?.dtype ?? 'fp32'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
await $TTSWorker.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showCallOverlay.set(true);
|
||||||
|
showControls.set(true);
|
||||||
|
} catch (err) {
|
||||||
|
// If the user denies the permission or an error occurs, show an error message
|
||||||
|
toast.error(
|
||||||
|
$i18n.t('Permission denied when accessing media devices')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
aria-label={$i18n.t('Voice mode')}
|
||||||
|
>
|
||||||
|
<Voice className="size-5" strokeWidth="2.5" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class=" flex items-center">
|
||||||
|
<Tooltip content={$i18n.t('Send message')}>
|
||||||
|
<button
|
||||||
|
id="send-message-button"
|
||||||
|
class="{!(prompt === '' && files.length === 0)
|
||||||
|
? 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
|
||||||
|
: 'text-white bg-gray-200 dark:text-gray-900 dark:bg-gray-700 disabled'} transition rounded-full p-1.5 self-center"
|
||||||
|
type="submit"
|
||||||
|
disabled={prompt === '' && files.length === 0}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="size-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M8 14a.75.75 0 0 1-.75-.75V4.56L4.03 7.78a.75.75 0 0 1-1.06-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 0 1-1.06 1.06L8.75 4.56v8.69A.75.75 0 0 1 8 14Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user