enh: image compression

This commit is contained in:
Timothy Jaeryang Baek
2024-12-24 23:28:14 -07:00
parent 591aac5e16
commit 326514be4e
4 changed files with 160 additions and 7 deletions

View File

@@ -7,7 +7,7 @@
const i18n = getContext('i18n');
import { config, mobile, settings } from '$lib/stores';
import { blobToFile } from '$lib/utils';
import { blobToFile, compressImage } from '$lib/utils';
import Tooltip from '../common/Tooltip.svelte';
import RichTextInput from '../common/RichTextInput.svelte';
@@ -100,15 +100,28 @@
if (['image/gif', 'image/webp', 'image/jpeg', 'image/png'].includes(file['type'])) {
let reader = new FileReader();
reader.onload = (event) => {
reader.onload = async (event) => {
let imageUrl = event.target.result;
if ($settings?.imageCompression ?? false) {
const width = $settings?.imageCompressionSize?.width ?? null;
const height = $settings?.imageCompressionSize?.height ?? null;
if (width || height) {
imageUrl = await compressImage(imageUrl, width, height);
}
}
files = [
...files,
{
type: 'image',
url: `${event.target.result}`
url: `${imageUrl}`
}
];
};
reader.readAsDataURL(file);
} else {
uploadFileHandler(file);

View File

@@ -19,7 +19,7 @@
showControls
} from '$lib/stores';
import { blobToFile, createMessagesList, findWordIndices } from '$lib/utils';
import { blobToFile, compressImage, createMessagesList, findWordIndices } from '$lib/utils';
import { transcribeAudio } from '$lib/apis/audio';
import { uploadFile } from '$lib/apis/files';
import { getTools } from '$lib/apis/tools';
@@ -244,12 +244,23 @@
return;
}
let reader = new FileReader();
reader.onload = (event) => {
reader.onload = async (event) => {
let imageUrl = event.target.result;
if ($settings?.imageCompression ?? false) {
const width = $settings?.imageCompressionSize?.width ?? null;
const height = $settings?.imageCompressionSize?.height ?? null;
if (width || height) {
imageUrl = await compressImage(imageUrl, width, height);
}
}
files = [
...files,
{
type: 'image',
url: `${event.target.result}`
url: `${imageUrl}`
}
];
};

View File

@@ -37,6 +37,12 @@
let chatBubble = true;
let chatDirection: 'LTR' | 'RTL' = 'LTR';
let imageCompression = false;
let imageCompressionSize = {
width: '',
height: ''
};
// Admin - Show Update Available Toast
let showUpdateToast = true;
let showChangelog = true;
@@ -95,6 +101,11 @@
saveSettings({ voiceInterruption: voiceInterruption });
};
const toggleImageCompression = async () => {
imageCompression = !imageCompression;
saveSettings({ imageCompression });
};
const toggleHapticFeedback = async () => {
hapticFeedback = !hapticFeedback;
saveSettings({ hapticFeedback: hapticFeedback });
@@ -176,7 +187,8 @@
const updateInterfaceHandler = async () => {
saveSettings({
models: [defaultModelId]
models: [defaultModelId],
imageCompressionSize: imageCompressionSize
});
};
@@ -206,6 +218,9 @@
hapticFeedback = $settings.hapticFeedback ?? false;
imageCompression = $settings.imageCompression ?? false;
imageCompressionSize = $settings.imageCompressionSize ?? { width: '', height: '' };
defaultModelId = $settings?.models?.at(0) ?? '';
if ($config?.default_models) {
defaultModelId = $config.default_models.split(',')[0];
@@ -662,6 +677,53 @@
</button>
</div>
</div>
<div class=" my-1.5 text-sm font-medium">{$i18n.t('File')}</div>
<div>
<div class=" py-0.5 flex w-full justify-between">
<div class=" self-center text-xs">{$i18n.t('Image Compression')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
on:click={() => {
toggleImageCompression();
}}
type="button"
>
{#if imageCompression === true}
<span class="ml-2 self-center">{$i18n.t('On')}</span>
{:else}
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
{/if}
</button>
</div>
</div>
{#if imageCompression}
<div>
<div class=" py-0.5 flex w-full justify-between text-xs">
<div class=" self-center text-xs">{$i18n.t('Image Max Compression Size')}</div>
<div>
<input
bind:value={imageCompressionSize.width}
type="number"
class="w-20 bg-transparent outline-none text-center"
min="0"
placeholder="Width"
/>x
<input
bind:value={imageCompressionSize.height}
type="number"
class="w-20 bg-transparent outline-none text-center"
min="0"
placeholder="Height"
/>
</div>
</div>
</div>
{/if}
</div>
</div>