refactor(frontend): saved and transcription results show where they were asked, not in a toast
This commit is contained in:
1 parent
58b4346166
commit
fb869e767b
7 files changed
+127
-36
No files matched your search
@@ -12,6 +12,7 @@
|
||||
import Reactions from "#lib/components/Reactions.svelte";
|
||||
import ReplyHeader from "#lib/components/ReplyHeader.svelte";
|
||||
import MessageReadItem from "#lib/components/read/MessageReadItem.svelte";
|
||||
import SavedItem from "#lib/components/SavedItem.svelte";
|
||||
import Avatar from "#lib/components/ui/Avatar.svelte";
|
||||
import ContextMenu from "#lib/components/ui/ContextMenu.svelte";
|
||||
import ContextMenuItem from "#lib/components/ui/ContextMenuItem.svelte";
|
||||
@@ -333,13 +334,11 @@
|
||||
>
|
||||
{/if}
|
||||
{#if savedUi.available && !savedUi.isSavedChat(message.chat_id)}
|
||||
<ContextMenuItem
|
||||
icon="forward"
|
||||
onselect={() => savedUi.forward(message.chat_id, message.message_id)}
|
||||
>{message.deleted_at || message.is_self_destruct
|
||||
? t("saved.copy")
|
||||
: t("saved.forward")}</ContextMenuItem
|
||||
>
|
||||
<SavedItem
|
||||
chatId={message.chat_id}
|
||||
copy={Boolean(message.deleted_at || message.is_self_destruct)}
|
||||
messageId={message.message_id}
|
||||
/>
|
||||
{/if}
|
||||
<CopyItem
|
||||
done={t("chat.menu.linkCopied")}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
let text = $state("");
|
||||
let sending = $state(false);
|
||||
let failure = $state<string | null>(null);
|
||||
let file = $state<File | null>(null);
|
||||
let caption = $state("");
|
||||
let voice = $state(false);
|
||||
@@ -49,11 +50,13 @@
|
||||
return;
|
||||
}
|
||||
sending = true;
|
||||
if (await savedUi.send({ text: message })) {
|
||||
const result = await savedUi.send({ text: message });
|
||||
sending = false;
|
||||
failure = result.ok ? null : t(result.label);
|
||||
if (result.ok) {
|
||||
text = "";
|
||||
requestAnimationFrame(fit);
|
||||
}
|
||||
sending = false;
|
||||
}
|
||||
|
||||
async function sendFile() {
|
||||
@@ -61,13 +64,14 @@
|
||||
return;
|
||||
}
|
||||
sending = true;
|
||||
const sent = await savedUi.send({
|
||||
const result = await savedUi.send({
|
||||
file,
|
||||
text: caption.trim(),
|
||||
voice: isAudio && voice,
|
||||
});
|
||||
sending = false;
|
||||
if (sent) {
|
||||
failure = result.ok ? null : t(result.label);
|
||||
if (result.ok) {
|
||||
file = null;
|
||||
caption = "";
|
||||
}
|
||||
@@ -97,6 +101,7 @@
|
||||
|
||||
function onOpenChange(open: boolean) {
|
||||
if (!(open || sending)) {
|
||||
failure = null;
|
||||
if (!text) {
|
||||
text = caption;
|
||||
}
|
||||
@@ -108,6 +113,9 @@
|
||||
</script>
|
||||
|
||||
<div class="SavedComposer">
|
||||
{#if failure && !file}
|
||||
<p class="failure">{failure}</p>
|
||||
{/if}
|
||||
<div class="field">
|
||||
<textarea
|
||||
aria-label={t("saved.message")}
|
||||
@@ -189,6 +197,9 @@
|
||||
</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if failure}
|
||||
<p class="failure">{failure}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<Dialog.Close>
|
||||
@@ -212,6 +223,7 @@
|
||||
.SavedComposer {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
gap: 0.5rem;
|
||||
|
||||
@@ -225,6 +237,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.failure {
|
||||
flex-basis: 100%;
|
||||
margin: 0;
|
||||
padding: 0 0.25rem;
|
||||
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.dialog-body .failure {
|
||||
margin-top: 0.75rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import { ContextMenu } from "bits-ui";
|
||||
import { menuCloser } from "#lib/components/ui/ContextMenu.svelte";
|
||||
import Icon from "#lib/components/ui/Icon.svelte";
|
||||
import Spinner from "#lib/components/ui/Spinner.svelte";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
import { type SavedOutcome, savedUi } from "#lib/stores/saved.svelte.js";
|
||||
|
||||
interface Props {
|
||||
chatId: number;
|
||||
copy: boolean;
|
||||
messageId: number;
|
||||
}
|
||||
|
||||
const { chatId, copy, messageId }: Props = $props();
|
||||
|
||||
const DONE_DELAY = 900;
|
||||
const FAILED_DELAY = 2400;
|
||||
|
||||
const close = menuCloser();
|
||||
let busy = $state(false);
|
||||
let result = $state<SavedOutcome | null>(null);
|
||||
|
||||
const icon = $derived.by(() => {
|
||||
if (result === null) {
|
||||
return "forward";
|
||||
}
|
||||
return result.ok ? "check" : "warning";
|
||||
});
|
||||
|
||||
async function send() {
|
||||
if (busy || result !== null) {
|
||||
return;
|
||||
}
|
||||
busy = true;
|
||||
result = await savedUi.forward(chatId, messageId);
|
||||
busy = false;
|
||||
setTimeout(close, result.ok ? DONE_DELAY : FAILED_DELAY);
|
||||
}
|
||||
</script>
|
||||
|
||||
<ContextMenu.Item class="bg-menu-item" closeOnSelect={false} onSelect={send}>
|
||||
{#if busy}
|
||||
<Spinner color="gray" size="1.125rem" />
|
||||
{:else}
|
||||
<Icon name={icon} size="1.125rem" />
|
||||
{/if}
|
||||
{#if result}
|
||||
{t(result.label)}
|
||||
{:else}
|
||||
{copy ? t("saved.copy") : t("saved.forward")}
|
||||
{/if}
|
||||
</ContextMenu.Item>
|
||||
@@ -134,6 +134,8 @@
|
||||
</button>
|
||||
{#if stt.open}
|
||||
<div class="transcript">{stt.text}</div>
|
||||
{:else if stt.failure}
|
||||
<div class="transcript failed">{stt.failure}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -178,6 +180,11 @@
|
||||
color: var(--color-text);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.failed {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
|
||||
.RoundVideo {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -157,6 +157,8 @@
|
||||
</div>
|
||||
{#if stt.open}
|
||||
<div class="transcript">{stt.text}</div>
|
||||
{:else if stt.failure}
|
||||
<div class="transcript failed">{stt.failure}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -223,6 +225,11 @@
|
||||
color: var(--color-text);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.failed {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
|
||||
.toggle {
|
||||
cursor: pointer;
|
||||
|
||||
Reference in new issue
Block a user