feat(frontend): forwarded header, pinned bar, folder tabs, inline buttons, edit history and deleted accounts speak russian and english
This commit is contained in:
1 parent
0cd34f3037
commit
25364f4523
8 files changed
+50
-18
No files matched your search
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import ContextMenu from "#lib/components/ui/ContextMenu.svelte";
|
||||
import ContextMenuItem from "#lib/components/ui/ContextMenuItem.svelte";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
import { folders } from "#lib/stores/folders.svelte.js";
|
||||
import { policyUi } from "#lib/stores/policy.svelte.js";
|
||||
|
||||
@@ -10,7 +11,7 @@
|
||||
}
|
||||
|
||||
const tabs = $derived<Tab[]>([
|
||||
{ id: null, title: "All Chats" },
|
||||
{ id: null, title: t("folders.all") },
|
||||
...folders.list.map((folder) => ({
|
||||
id: folder.folder_id,
|
||||
title: folder.title,
|
||||
@@ -93,7 +94,7 @@
|
||||
{/snippet}
|
||||
{#snippet menu()}
|
||||
<ContextMenuItem icon="settings" onselect={() => editPolicy(tab)}>
|
||||
Политика захвата
|
||||
{t("settings.policy")}
|
||||
</ContextMenuItem>
|
||||
{/snippet}
|
||||
</ContextMenu>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { ForwardView } from "#lib/api/types.js";
|
||||
import { peerName } from "#lib/format/peer.js";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
import { peers } from "#lib/stores/peers.svelte.js";
|
||||
|
||||
interface Props {
|
||||
@@ -14,20 +15,20 @@
|
||||
);
|
||||
const name = $derived.by(() => {
|
||||
if (forward.kind === "channel") {
|
||||
return forward.chat_title ?? "Channel";
|
||||
return forward.chat_title ?? t("forward.channel");
|
||||
}
|
||||
if (forward.kind === "hidden") {
|
||||
return forward.from_name ?? "Hidden account";
|
||||
return forward.from_name ?? t("forward.hidden");
|
||||
}
|
||||
if (peer) {
|
||||
return peerName(peer);
|
||||
}
|
||||
return forward.from_name ?? "Unknown";
|
||||
return forward.from_name ?? t("forward.unknown");
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="ForwardHeader">
|
||||
<span class="label">Forwarded from</span>
|
||||
<span class="label">{t("forward.from")}</span>
|
||||
<span class="name">{name}</span>
|
||||
{#if forward.signature}
|
||||
<span class="signature">({forward.signature})</span>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { InlineButton } from "#lib/api/types.js";
|
||||
import { safeHref } from "#lib/format/url.js";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
|
||||
interface Props {
|
||||
rows: InlineButton[][];
|
||||
@@ -43,7 +44,7 @@
|
||||
type="button"
|
||||
>
|
||||
<span class="label"
|
||||
>{copied === key ? "Скопировано" : button.text}</span
|
||||
>{copied === key ? t("inline.copied") : button.text}</span
|
||||
>
|
||||
</button>
|
||||
{:else}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import Icon from "#lib/components/ui/Icon.svelte";
|
||||
import Spinner from "#lib/components/ui/Spinner.svelte";
|
||||
import { formatFull } from "#lib/format/datetime.js";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
import { toasts } from "#lib/stores/toasts.svelte.js";
|
||||
|
||||
interface Props {
|
||||
@@ -33,7 +34,7 @@
|
||||
versions = text;
|
||||
mediaVersions = media;
|
||||
})
|
||||
.catch(() => toasts.error("Failed to load edit history"))
|
||||
.catch(() => toasts.error(t("versions.failed")))
|
||||
.finally(() => {
|
||||
loading = false;
|
||||
});
|
||||
@@ -46,8 +47,8 @@
|
||||
<Dialog.Overlay class="dialog-overlay" />
|
||||
<Dialog.Content class="dialog-content">
|
||||
<header class="dialog-head">
|
||||
<Dialog.Title class="dialog-title">Edit history</Dialog.Title>
|
||||
<Dialog.Close aria-label="Close" class="dialog-close">
|
||||
<Dialog.Title class="dialog-title">{t("versions.title")}</Dialog.Title>
|
||||
<Dialog.Close aria-label={t("common.close")} class="dialog-close">
|
||||
<Icon name="close" size="1.25rem" />
|
||||
</Dialog.Close>
|
||||
</header>
|
||||
@@ -55,11 +56,11 @@
|
||||
{#if loading}
|
||||
<div class="centered"><Spinner /></div>
|
||||
{:else if versions.length === 0 && mediaVersions.length === 0}
|
||||
<p class="empty">No versions recorded.</p>
|
||||
<p class="empty">{t("versions.none")}</p>
|
||||
{:else}
|
||||
{#if mediaVersions.length > 0}
|
||||
<div class="media-versions">
|
||||
<span class="media-label">Media versions</span>
|
||||
<span class="media-label">{t("versions.media")}</span>
|
||||
<div class="media-strip">
|
||||
{#each mediaVersions as media (media.id)}
|
||||
<MediaVersionThumb version={media} />
|
||||
@@ -70,12 +71,14 @@
|
||||
{#each versions as version, index (version.observed_at)}
|
||||
<div class="version">
|
||||
<div class="version-meta">
|
||||
<span class="version-label">Version {index + 1}</span>
|
||||
<span class="version-label"
|
||||
>{t("versions.version", { number: index + 1 })}</span
|
||||
>
|
||||
<span class="version-date"
|
||||
>{formatFull(version.observed_at)}</span
|
||||
>
|
||||
</div>
|
||||
<div class="version-text">{version.text ?? "(no text)"}</div>
|
||||
<div class="version-text">{version.text ?? t("feed.noText")}</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import type { PinnedView } from "#lib/api/types.js";
|
||||
import Icon from "#lib/components/ui/Icon.svelte";
|
||||
import { mediaKindLabel } from "#lib/format/media.js";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
import { accounts } from "#lib/stores/accounts.svelte.js";
|
||||
|
||||
interface Props {
|
||||
@@ -19,7 +20,7 @@
|
||||
? (pinned.text ??
|
||||
(pinned.media_kind
|
||||
? mediaKindLabel(pinned.media_kind)
|
||||
: "Pinned message"))
|
||||
: t("pinned.message")))
|
||||
: ""
|
||||
);
|
||||
|
||||
@@ -56,7 +57,7 @@
|
||||
>
|
||||
<Icon name="pin" size="1.125rem" />
|
||||
<span class="body">
|
||||
<span class="label">Pinned message</span>
|
||||
<span class="label">{t("pinned.message")}</span>
|
||||
<span class="preview">{preview}</span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Account, PeerView } from "#lib/api/types.js";
|
||||
import { t } from "#lib/i18n/locale.svelte.js";
|
||||
|
||||
const PEER_COLOR_COUNT = 7;
|
||||
|
||||
@@ -11,7 +12,7 @@ export function peerName(peer: PeerView | null): string {
|
||||
return "";
|
||||
}
|
||||
if (peer.is_deleted_account) {
|
||||
return "Удалённый аккаунт";
|
||||
return t("chat.deletedAccount");
|
||||
}
|
||||
const parts = [peer.first_name, peer.last_name].filter(Boolean);
|
||||
if (parts.length > 0) {
|
||||
@@ -20,7 +21,7 @@ export function peerName(peer: PeerView | null): string {
|
||||
if (peer.username) {
|
||||
return `@${peer.username}`;
|
||||
}
|
||||
return "Удалённый аккаунт";
|
||||
return t("chat.deletedAccount");
|
||||
}
|
||||
|
||||
export function accountName(account: Account): string {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { login } from "#lib/i18n/messages/login.js";
|
||||
import { media } from "#lib/i18n/messages/media.js";
|
||||
import { menu } from "#lib/i18n/messages/menu.js";
|
||||
import { notes } from "#lib/i18n/messages/notes.js";
|
||||
import { parts } from "#lib/i18n/messages/parts.js";
|
||||
import { policy } from "#lib/i18n/messages/policy.js";
|
||||
import { presence } from "#lib/i18n/messages/presence.js";
|
||||
import { profile } from "#lib/i18n/messages/profile.js";
|
||||
@@ -39,6 +40,7 @@ export const messages = {
|
||||
...media,
|
||||
...menu,
|
||||
...notes,
|
||||
...parts,
|
||||
...policy,
|
||||
...presence,
|
||||
...profile,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { Messages } from "#lib/i18n/types.js";
|
||||
|
||||
export const parts = {
|
||||
"folders.all": { en: "All Chats", ru: "Все чаты" },
|
||||
"forward.channel": { en: "Channel", ru: "Канал" },
|
||||
"forward.from": { en: "Forwarded from", ru: "Переслано от" },
|
||||
"forward.hidden": { en: "Hidden account", ru: "Скрытый аккаунт" },
|
||||
"forward.unknown": { en: "Unknown sender", ru: "Неизвестный отправитель" },
|
||||
"inline.copied": { en: "Copied", ru: "Скопировано" },
|
||||
"pinned.message": { en: "Pinned Message", ru: "Закреплённое сообщение" },
|
||||
"versions.failed": {
|
||||
en: "Couldn't load the edit history",
|
||||
ru: "Не удалось загрузить историю изменений",
|
||||
},
|
||||
"versions.media": { en: "Media versions", ru: "Версии медиа" },
|
||||
"versions.none": {
|
||||
en: "No versions saved.",
|
||||
ru: "Версии не сохранились.",
|
||||
},
|
||||
"versions.title": { en: "Edit history", ru: "История изменений" },
|
||||
"versions.version": { en: "Version {number}", ru: "Версия {number}" },
|
||||
} satisfies Messages;
|
||||
Reference in new issue
Block a user