Spaces:
Sleeping
Sleeping
feat(front): hide bottom disclaimer when focused on mobile
Browse files
src/lib/components/chat/ChatInput.svelte
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
-
import { browser } from "$app/environment";
|
| 3 |
import { createEventDispatcher, onMount } from "svelte";
|
| 4 |
|
| 5 |
import HoverTooltip from "$lib/components/HoverTooltip.svelte";
|
|
@@ -24,7 +23,7 @@
|
|
| 24 |
import { captureScreen } from "$lib/utils/screenshot";
|
| 25 |
import IconScreenshot from "../icons/IconScreenshot.svelte";
|
| 26 |
import { loginModalOpen } from "$lib/stores/loginModal";
|
| 27 |
-
|
| 28 |
interface Props {
|
| 29 |
files?: File[];
|
| 30 |
mimeTypes?: string[];
|
|
@@ -37,6 +36,7 @@
|
|
| 37 |
modelIsMultimodal?: boolean;
|
| 38 |
children?: import("svelte").Snippet;
|
| 39 |
onPaste?: (e: ClipboardEvent) => void;
|
|
|
|
| 40 |
}
|
| 41 |
|
| 42 |
let {
|
|
@@ -51,6 +51,7 @@
|
|
| 51 |
modelIsMultimodal = false,
|
| 52 |
children,
|
| 53 |
onPaste,
|
|
|
|
| 54 |
}: Props = $props();
|
| 55 |
|
| 56 |
const onFileChange = async (e: Event) => {
|
|
@@ -85,21 +86,6 @@
|
|
| 85 |
};
|
| 86 |
});
|
| 87 |
|
| 88 |
-
function isVirtualKeyboard(): boolean {
|
| 89 |
-
if (!browser) return false;
|
| 90 |
-
|
| 91 |
-
// Check for touch capability
|
| 92 |
-
if (navigator.maxTouchPoints > 0 && screen.width <= 768) return true;
|
| 93 |
-
|
| 94 |
-
// Check for touch events
|
| 95 |
-
if ("ontouchstart" in window) return true;
|
| 96 |
-
|
| 97 |
-
// Fallback to user agent string check
|
| 98 |
-
const userAgent = navigator.userAgent.toLowerCase();
|
| 99 |
-
|
| 100 |
-
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
|
| 101 |
-
}
|
| 102 |
-
|
| 103 |
function adjustTextareaHeight() {
|
| 104 |
if (!textareaElement) {
|
| 105 |
return;
|
|
@@ -180,6 +166,8 @@
|
|
| 180 |
}}
|
| 181 |
{placeholder}
|
| 182 |
{disabled}
|
|
|
|
|
|
|
| 183 |
></textarea>
|
| 184 |
|
| 185 |
{#if !showNoTools}
|
|
|
|
| 1 |
<script lang="ts">
|
|
|
|
| 2 |
import { createEventDispatcher, onMount } from "svelte";
|
| 3 |
|
| 4 |
import HoverTooltip from "$lib/components/HoverTooltip.svelte";
|
|
|
|
| 23 |
import { captureScreen } from "$lib/utils/screenshot";
|
| 24 |
import IconScreenshot from "../icons/IconScreenshot.svelte";
|
| 25 |
import { loginModalOpen } from "$lib/stores/loginModal";
|
| 26 |
+
import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard";
|
| 27 |
interface Props {
|
| 28 |
files?: File[];
|
| 29 |
mimeTypes?: string[];
|
|
|
|
| 36 |
modelIsMultimodal?: boolean;
|
| 37 |
children?: import("svelte").Snippet;
|
| 38 |
onPaste?: (e: ClipboardEvent) => void;
|
| 39 |
+
focused?: boolean;
|
| 40 |
}
|
| 41 |
|
| 42 |
let {
|
|
|
|
| 51 |
modelIsMultimodal = false,
|
| 52 |
children,
|
| 53 |
onPaste,
|
| 54 |
+
focused = $bindable(false),
|
| 55 |
}: Props = $props();
|
| 56 |
|
| 57 |
const onFileChange = async (e: Event) => {
|
|
|
|
| 86 |
};
|
| 87 |
});
|
| 88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
function adjustTextareaHeight() {
|
| 90 |
if (!textareaElement) {
|
| 91 |
return;
|
|
|
|
| 166 |
}}
|
| 167 |
{placeholder}
|
| 168 |
{disabled}
|
| 169 |
+
onfocus={() => (focused = true)}
|
| 170 |
+
onblur={() => (focused = false)}
|
| 171 |
></textarea>
|
| 172 |
|
| 173 |
{#if !showNoTools}
|
src/lib/components/chat/ChatWindow.svelte
CHANGED
|
@@ -38,6 +38,7 @@
|
|
| 38 |
import type { ToolFront } from "$lib/types/Tool";
|
| 39 |
import { loginModalOpen } from "$lib/stores/loginModal";
|
| 40 |
import { beforeNavigate } from "$app/navigation";
|
|
|
|
| 41 |
|
| 42 |
interface Props {
|
| 43 |
messages?: Message[];
|
|
@@ -230,6 +231,7 @@
|
|
| 230 |
)
|
| 231 |
);
|
| 232 |
let isFileUploadEnabled = $derived(activeMimeTypes.length > 0);
|
|
|
|
| 233 |
</script>
|
| 234 |
|
| 235 |
<svelte:window
|
|
@@ -411,8 +413,11 @@
|
|
| 411 |
e.preventDefault();
|
| 412 |
handleSubmit();
|
| 413 |
}}
|
| 414 |
-
class=
|
| 415 |
-
|
|
|
|
|
|
|
|
|
|
| 416 |
>
|
| 417 |
{#if onDrag && isFileUploadEnabled}
|
| 418 |
<FileDropzone bind:files bind:onDrag mimeTypes={activeMimeTypes} />
|
|
@@ -436,6 +441,7 @@
|
|
| 436 |
disabled={isReadOnly || lastIsError}
|
| 437 |
modelHasTools={currentModel.tools}
|
| 438 |
modelIsMultimodal={currentModel.multimodal}
|
|
|
|
| 439 |
/>
|
| 440 |
{/if}
|
| 441 |
|
|
@@ -474,7 +480,10 @@
|
|
| 474 |
{/if}
|
| 475 |
</form>
|
| 476 |
<div
|
| 477 |
-
class=
|
|
|
|
|
|
|
|
|
|
| 478 |
>
|
| 479 |
<p>
|
| 480 |
Model:
|
|
|
|
| 38 |
import type { ToolFront } from "$lib/types/Tool";
|
| 39 |
import { loginModalOpen } from "$lib/stores/loginModal";
|
| 40 |
import { beforeNavigate } from "$app/navigation";
|
| 41 |
+
import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard";
|
| 42 |
|
| 43 |
interface Props {
|
| 44 |
messages?: Message[];
|
|
|
|
| 231 |
)
|
| 232 |
);
|
| 233 |
let isFileUploadEnabled = $derived(activeMimeTypes.length > 0);
|
| 234 |
+
let focused = $state(false);
|
| 235 |
</script>
|
| 236 |
|
| 237 |
<svelte:window
|
|
|
|
| 413 |
e.preventDefault();
|
| 414 |
handleSubmit();
|
| 415 |
}}
|
| 416 |
+
class={{
|
| 417 |
+
"relative flex w-full max-w-4xl flex-1 items-center rounded-xl border bg-gray-100 dark:border-gray-600 dark:bg-gray-700": true,
|
| 418 |
+
"opacity-30": isReadOnly,
|
| 419 |
+
"max-sm:mb-4": focused && isVirtualKeyboard(),
|
| 420 |
+
}}
|
| 421 |
>
|
| 422 |
{#if onDrag && isFileUploadEnabled}
|
| 423 |
<FileDropzone bind:files bind:onDrag mimeTypes={activeMimeTypes} />
|
|
|
|
| 441 |
disabled={isReadOnly || lastIsError}
|
| 442 |
modelHasTools={currentModel.tools}
|
| 443 |
modelIsMultimodal={currentModel.multimodal}
|
| 444 |
+
bind:focused
|
| 445 |
/>
|
| 446 |
{/if}
|
| 447 |
|
|
|
|
| 480 |
{/if}
|
| 481 |
</form>
|
| 482 |
<div
|
| 483 |
+
class={{
|
| 484 |
+
"mt-2 flex justify-between self-stretch px-1 text-xs text-gray-400/90 max-md:mb-2 max-sm:gap-2": true,
|
| 485 |
+
"max-sm:hidden": focused && isVirtualKeyboard(),
|
| 486 |
+
}}
|
| 487 |
>
|
| 488 |
<p>
|
| 489 |
Model:
|
src/lib/utils/isVirtualKeyboard.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { browser } from "$app/environment";
|
| 2 |
+
|
| 3 |
+
export function isVirtualKeyboard(): boolean {
|
| 4 |
+
if (!browser) return false;
|
| 5 |
+
|
| 6 |
+
// Check for touch capability
|
| 7 |
+
if (navigator.maxTouchPoints > 0 && screen.width <= 768) return true;
|
| 8 |
+
|
| 9 |
+
// Check for touch events
|
| 10 |
+
if ("ontouchstart" in window) return true;
|
| 11 |
+
|
| 12 |
+
// Fallback to user agent string check
|
| 13 |
+
const userAgent = navigator.userAgent.toLowerCase();
|
| 14 |
+
|
| 15 |
+
return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
|
| 16 |
+
}
|