neven4 nsarrazin HF Staff commited on
Commit
8e494b0
·
unverified ·
1 Parent(s): 0f633f3

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 ||