Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Disable text streaming if user prefers reduced animation (#1131)
Browse files* Disable text streaming if user prefers reduced animation
* Simplify filtering of stream updates
---------
Co-authored-by: Nathan Sarrazin <[email protected]>
src/lib/components/chat/ChatMessage.svelte
CHANGED
@@ -37,6 +37,7 @@
|
|
37 |
import type { ToolFront } from "$lib/types/Tool";
|
38 |
import { base } from "$app/paths";
|
39 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
|
|
40 |
import Modal from "../Modal.svelte";
|
41 |
import { toolHasName } from "$lib/utils/tools";
|
42 |
|
@@ -87,6 +88,7 @@
|
|
87 |
|
88 |
let initialized = false;
|
89 |
|
|
|
90 |
const renderer = new marked.Renderer();
|
91 |
// For code blocks with simple backticks
|
92 |
renderer.codespan = (code) => {
|
@@ -123,6 +125,10 @@
|
|
123 |
!message.content && (webSearchIsDone || (searchUpdates && searchUpdates.length === 0));
|
124 |
|
125 |
afterUpdate(() => {
|
|
|
|
|
|
|
|
|
126 |
loadingEl?.$destroy();
|
127 |
clearTimeout(pendingTimeout);
|
128 |
|
@@ -364,6 +370,9 @@
|
|
364 |
class="prose max-w-none max-sm:prose-sm dark:prose-invert prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
365 |
bind:this={contentEl}
|
366 |
>
|
|
|
|
|
|
|
367 |
{#each tokens as token}
|
368 |
{#if token.type === "code"}
|
369 |
<CodeBlock lang={token.lang} code={unsanitizeMd(token.text)} />
|
|
|
37 |
import type { ToolFront } from "$lib/types/Tool";
|
38 |
import { base } from "$app/paths";
|
39 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
40 |
+
import { isReducedMotion } from "$lib/utils/isReduceMotion";
|
41 |
import Modal from "../Modal.svelte";
|
42 |
import { toolHasName } from "$lib/utils/tools";
|
43 |
|
|
|
88 |
|
89 |
let initialized = false;
|
90 |
|
91 |
+
const reducedMotionMode = isReducedMotion(window);
|
92 |
const renderer = new marked.Renderer();
|
93 |
// For code blocks with simple backticks
|
94 |
renderer.codespan = (code) => {
|
|
|
125 |
!message.content && (webSearchIsDone || (searchUpdates && searchUpdates.length === 0));
|
126 |
|
127 |
afterUpdate(() => {
|
128 |
+
if (reducedMotionMode) {
|
129 |
+
return;
|
130 |
+
}
|
131 |
+
|
132 |
loadingEl?.$destroy();
|
133 |
clearTimeout(pendingTimeout);
|
134 |
|
|
|
370 |
class="prose max-w-none max-sm:prose-sm dark:prose-invert prose-headings:font-semibold prose-h1:text-lg prose-h2:text-base prose-h3:text-base prose-pre:bg-gray-800 dark:prose-pre:bg-gray-900"
|
371 |
bind:this={contentEl}
|
372 |
>
|
373 |
+
{#if isLast && loading && reducedMotionMode}
|
374 |
+
<IconLoading classNames="loading inline ml-2 first:ml-0" />
|
375 |
+
{/if}
|
376 |
{#each tokens as token}
|
377 |
{#if token.type === "code"}
|
378 |
<CodeBlock lang={token.lang} code={unsanitizeMd(token.text)} />
|
src/lib/utils/isReduceMotion.ts
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export function isReducedMotion(window: Window) {
|
2 |
+
const { matchMedia } = window;
|
3 |
+
|
4 |
+
return matchMedia("(prefers-reduced-motion: reduce)").matches;
|
5 |
+
}
|
src/routes/conversation/[id]/+page.svelte
CHANGED
@@ -23,6 +23,7 @@
|
|
23 |
import { fetchMessageUpdates } from "$lib/utils/messageUpdates";
|
24 |
import { createConvTreeStore } from "$lib/stores/convTree";
|
25 |
import type { v4 } from "uuid";
|
|
|
26 |
import { useSettingsStore } from "$lib/stores/settings.js";
|
27 |
|
28 |
export let data;
|
@@ -79,6 +80,7 @@
|
|
79 |
$isAborted = false;
|
80 |
loading = true;
|
81 |
pending = true;
|
|
|
82 |
|
83 |
const base64Files = await Promise.all(
|
84 |
(files ?? []).map((file) =>
|
@@ -215,6 +217,7 @@
|
|
215 |
files = [];
|
216 |
|
217 |
const messageUpdates: MessageUpdate[] = [];
|
|
|
218 |
for await (const update of messageUpdatesIterator) {
|
219 |
if ($isAborted) {
|
220 |
messageUpdatesAbortController.abort();
|
@@ -234,9 +237,8 @@
|
|
234 |
|
235 |
messageUpdates.push(update);
|
236 |
|
237 |
-
if (update.type === MessageUpdateType.Stream) {
|
238 |
pending = false;
|
239 |
-
messageToWriteTo.content += update.token;
|
240 |
messages = [...messages];
|
241 |
} else if (
|
242 |
update.type === MessageUpdateType.WebSearch ||
|
|
|
23 |
import { fetchMessageUpdates } from "$lib/utils/messageUpdates";
|
24 |
import { createConvTreeStore } from "$lib/stores/convTree";
|
25 |
import type { v4 } from "uuid";
|
26 |
+
import { isReducedMotion } from "$lib/utils/isReduceMotion.js";
|
27 |
import { useSettingsStore } from "$lib/stores/settings.js";
|
28 |
|
29 |
export let data;
|
|
|
80 |
$isAborted = false;
|
81 |
loading = true;
|
82 |
pending = true;
|
83 |
+
const reducedMotionMode = isReducedMotion(window);
|
84 |
|
85 |
const base64Files = await Promise.all(
|
86 |
(files ?? []).map((file) =>
|
|
|
217 |
files = [];
|
218 |
|
219 |
const messageUpdates: MessageUpdate[] = [];
|
220 |
+
|
221 |
for await (const update of messageUpdatesIterator) {
|
222 |
if ($isAborted) {
|
223 |
messageUpdatesAbortController.abort();
|
|
|
237 |
|
238 |
messageUpdates.push(update);
|
239 |
|
240 |
+
if (update.type === MessageUpdateType.Stream && !reducedMotionMode) {
|
241 |
pending = false;
|
|
|
242 |
messages = [...messages];
|
243 |
} else if (
|
244 |
update.type === MessageUpdateType.WebSearch ||
|