summaryrefslogtreecommitdiffhomepage
path: root/src/features/chat/ui/PendingInputWarning.svelte
blob: c9e675e98529fd5a5ba36cf8b7d9475cad14a647 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<script lang="ts">
  import { onMount } from "svelte";
  import type { PendingInput } from "../pending-inputs";

  let {
    input,
    onDiscard,
  }: {
    input: PendingInput;
    onDiscard: (requestId: string) => void;
  } = $props();

  let visible = $state(false);

  // Presentation only: each keyed row gets one grace period, including restored
  // or rejected inputs. Prop updates never restart it. Confirmation/discard
  // removes the row, cancelling the timer along with any other unmount.
  onMount(() => {
    const timer = setTimeout(() => {
      visible = true;
    }, 1000);
    return () => clearTimeout(timer);
  });
</script>

{#if visible}
  <div class="m-3 rounded border border-warning p-3 text-sm" role="status">
    <p>
      {input.rejection
        ? `Message rejected: ${input.rejection}`
        : "Delivery unconfirmed. Your input is saved on this device."}
    </p>
    <p>Check the conversation history before sending again to avoid a duplicate.</p>
    <textarea
      class="textarea textarea-bordered mt-2 w-full"
      aria-label="Saved message"
      readonly
      value={input.request.type === "chat.send" ? input.request.message : input.request.text}
    ></textarea>
    {#each input.request.images ?? [] as image}
      <img class="my-2 max-h-32" src={image.url} alt="Saved attachment" />
    {/each}
    <button class="btn btn-sm mt-2" onclick={() => onDiscard(input.request.requestId)}
      >Discard saved copy</button
    >
  </div>
{/if}