localize Inbox/Notifications
This commit is contained in:
parent
1495a4b01e
commit
3f4e07ce16
9 changed files with 190 additions and 54 deletions
|
|
@ -451,5 +451,61 @@
|
|||
"broken_message": "Broken message",
|
||||
"empty_message": "Empty message",
|
||||
"edited": " (edited)"
|
||||
},
|
||||
"Inbox": {
|
||||
"inbox": "Inbox",
|
||||
"invites": "Invites",
|
||||
"notifications": "Notifications",
|
||||
|
||||
"notification_messages": "Notifications",
|
||||
"filter": "Filter",
|
||||
"all_notifications": "All Notifications",
|
||||
"highlighted": "Highlighted",
|
||||
"mark_as_read": "Mark as Read",
|
||||
"open": "Open",
|
||||
"no_notifications": "No Notifications",
|
||||
"no_notifications_desc": "You don't have any new notifications to display yet.",
|
||||
"scroll_to_top": "Scroll to Top",
|
||||
|
||||
"encrypted": "Encrypted",
|
||||
"direct_message": "Direct Message",
|
||||
"space": "Space",
|
||||
"decline": "Decline",
|
||||
"accept": "Accept",
|
||||
"from": "From: ",
|
||||
"reason_label": "Reason: ",
|
||||
|
||||
"primary": "Primary",
|
||||
"public": "Public",
|
||||
"spam": "Spam",
|
||||
|
||||
"no_invites": "No Invites",
|
||||
"no_invites_known_desc": "When someone you share a room with sends you an invite, it'll show up here.",
|
||||
"no_invites_unknown_desc": "Invites from people outside your rooms will appear here.",
|
||||
"decline_all": "Decline All",
|
||||
|
||||
"spam_invites_count_one": "{{count}} Spam Invite",
|
||||
"spam_invites_count_other": "{{count}} Spam Invites",
|
||||
"spam_invites_desc": "Some of the following invites may contain harmful content or have been sent by banned users.",
|
||||
"report_all": "Report All",
|
||||
"block_all": "Block All",
|
||||
"hide_all": "Hide All",
|
||||
"view_all": "View All",
|
||||
"no_spam_invites": "No Spam Invites",
|
||||
"no_spam_invites_desc": "Invites detected as spam appear here.",
|
||||
|
||||
"invite_title": "Invite",
|
||||
"user_id": "User ID",
|
||||
"user_id_placeholder": "@username:server",
|
||||
"reason_optional": "Reason (Optional)",
|
||||
"invite_button": "Invite",
|
||||
|
||||
"notif_default": "Default",
|
||||
"notif_all_messages": "All Messages",
|
||||
"notif_mentions_keywords": "Mention & Keywords",
|
||||
"notif_mute": "Mute",
|
||||
|
||||
"unverified_device": "Unverified Device",
|
||||
"unverified_devices": "Unverified Devices"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -451,5 +451,63 @@
|
|||
"broken_message": "Повреждённое сообщение",
|
||||
"empty_message": "Пустое сообщение",
|
||||
"edited": " (изменено)"
|
||||
},
|
||||
"Inbox": {
|
||||
"inbox": "Входящие",
|
||||
"invites": "Приглашения",
|
||||
"notifications": "Уведомления",
|
||||
|
||||
"notification_messages": "Уведомления",
|
||||
"filter": "Фильтр",
|
||||
"all_notifications": "Все уведомления",
|
||||
"highlighted": "Выделенные",
|
||||
"mark_as_read": "Отметить прочитанным",
|
||||
"open": "Открыть",
|
||||
"no_notifications": "Нет уведомлений",
|
||||
"no_notifications_desc": "У вас пока нет новых уведомлений.",
|
||||
"scroll_to_top": "Наверх",
|
||||
|
||||
"encrypted": "Зашифровано",
|
||||
"direct_message": "Личное сообщение",
|
||||
"space": "Пространство",
|
||||
"decline": "Отклонить",
|
||||
"accept": "Принять",
|
||||
"from": "От: ",
|
||||
"reason_label": "Причина: ",
|
||||
|
||||
"primary": "Основные",
|
||||
"public": "Публичные",
|
||||
"spam": "Спам",
|
||||
|
||||
"no_invites": "Нет приглашений",
|
||||
"no_invites_known_desc": "Когда кто-то, с кем вы состоите в одной комнате, отправит вам приглашение, оно появится здесь.",
|
||||
"no_invites_unknown_desc": "Приглашения от людей за пределами ваших комнат появятся здесь.",
|
||||
"decline_all": "Отклонить все",
|
||||
|
||||
"spam_invites_count_one": "{{count}} спам-приглашение",
|
||||
"spam_invites_count_few": "{{count}} спам-приглашения",
|
||||
"spam_invites_count_many": "{{count}} спам-приглашений",
|
||||
"spam_invites_count_other": "{{count}} спам-приглашений",
|
||||
"spam_invites_desc": "Некоторые из этих приглашений могут содержать вредоносный контент или были отправлены забаненными пользователями.",
|
||||
"report_all": "Пожаловаться на все",
|
||||
"block_all": "Заблокировать всех",
|
||||
"hide_all": "Скрыть все",
|
||||
"view_all": "Показать все",
|
||||
"no_spam_invites": "Нет спам-приглашений",
|
||||
"no_spam_invites_desc": "Приглашения, распознанные как спам, появятся здесь.",
|
||||
|
||||
"invite_title": "Пригласить",
|
||||
"user_id": "ID пользователя",
|
||||
"user_id_placeholder": "@username:server",
|
||||
"reason_optional": "Причина (необязательно)",
|
||||
"invite_button": "Пригласить",
|
||||
|
||||
"notif_default": "По умолчанию",
|
||||
"notif_all_messages": "Все сообщения",
|
||||
"notif_mentions_keywords": "Упоминания и ключевые слова",
|
||||
"notif_mute": "Без уведомлений",
|
||||
|
||||
"unverified_device": "Неподтверждённое устройство",
|
||||
"unverified_devices": "Неподтверждённые устройства"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Box, config, Icon, Menu, MenuItem, PopOut, RectCords, Text } from 'folds';
|
||||
import React, { MouseEventHandler, ReactNode, useMemo, useState } from 'react';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { stopPropagation } from '../utils/keyboard';
|
||||
import {
|
||||
getRoomNotificationModeIcon,
|
||||
|
|
@ -20,16 +21,18 @@ const useRoomNotificationModes = (): RoomNotificationMode[] =>
|
|||
[]
|
||||
);
|
||||
|
||||
const useRoomNotificationModeStr = (): Record<RoomNotificationMode, string> =>
|
||||
useMemo(
|
||||
const useRoomNotificationModeStr = (): Record<RoomNotificationMode, string> => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => ({
|
||||
[RoomNotificationMode.Unset]: 'Default',
|
||||
[RoomNotificationMode.AllMessages]: 'All Messages',
|
||||
[RoomNotificationMode.SpecialMessages]: 'Mention & Keywords',
|
||||
[RoomNotificationMode.Mute]: 'Mute',
|
||||
[RoomNotificationMode.Unset]: t('Inbox.notif_default'),
|
||||
[RoomNotificationMode.AllMessages]: t('Inbox.notif_all_messages'),
|
||||
[RoomNotificationMode.SpecialMessages]: t('Inbox.notif_mentions_keywords'),
|
||||
[RoomNotificationMode.Mute]: t('Inbox.notif_mute'),
|
||||
}),
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
type NotificationModeSwitcherProps = {
|
||||
roomId: string;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
import { Room } from 'matrix-js-sdk';
|
||||
import { isKeyHotkey } from 'is-hotkey';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { stopPropagation } from '../../utils/keyboard';
|
||||
import { useDirectUsers } from '../../hooks/useDirectUsers';
|
||||
import { getMxIdLocalPart, getMxIdServer, isUserId } from '../../utils/matrix';
|
||||
|
|
@ -56,6 +57,7 @@ type InviteUserProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const alive = useAlive();
|
||||
|
||||
|
|
@ -169,7 +171,7 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
|
|||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4" truncate>
|
||||
Invite
|
||||
{t('Inbox.invite_title')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -187,14 +189,14 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
|
|||
gap="400"
|
||||
>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">User ID</Text>
|
||||
<Text size="L400">{t('Inbox.user_id')}</Text>
|
||||
<div>
|
||||
<Input
|
||||
size="500"
|
||||
ref={inputRef}
|
||||
onChange={handleSearchChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="@username:server"
|
||||
placeholder={t('Inbox.user_id_placeholder')}
|
||||
name="userIdInput"
|
||||
variant="Background"
|
||||
disabled={inviting}
|
||||
|
|
@ -260,7 +262,7 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
|
|||
</div>
|
||||
</Box>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Reason (Optional)</Text>
|
||||
<Text size="L400">{t('Inbox.reason_optional')}</Text>
|
||||
<TextArea
|
||||
size="500"
|
||||
name="reasonInput"
|
||||
|
|
@ -279,7 +281,7 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
|
|||
disabled={!validUserId || inviting}
|
||||
before={inviting && <Spinner size="200" variant="Primary" fill="Solid" />}
|
||||
>
|
||||
<Text size="B400">Invite</Text>
|
||||
<Text size="B400">{t('Inbox.invite_button')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Avatar, Box, Icon, Icons, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { NavCategory, NavItem, NavItemContent, NavLink } from '../../../components/nav';
|
||||
import { getInboxInvitesPath, getInboxNotificationsPath } from '../../pathUtils';
|
||||
|
|
@ -13,6 +14,7 @@ import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMappe
|
|||
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
|
||||
|
||||
function InvitesNavItem() {
|
||||
const { t } = useTranslation();
|
||||
const invitesSelected = useInboxInvitesSelected();
|
||||
const allInvites = useAtomValue(allInvitesAtom);
|
||||
const inviteCount = allInvites.length;
|
||||
|
|
@ -32,7 +34,7 @@ function InvitesNavItem() {
|
|||
</Avatar>
|
||||
<Box as="span" grow="Yes">
|
||||
<Text as="span" size="Inherit" truncate>
|
||||
Invites
|
||||
{t('Inbox.invites')}
|
||||
</Text>
|
||||
</Box>
|
||||
{inviteCount > 0 && <UnreadBadge highlight count={inviteCount} />}
|
||||
|
|
@ -44,6 +46,7 @@ function InvitesNavItem() {
|
|||
}
|
||||
|
||||
export function Inbox() {
|
||||
const { t } = useTranslation();
|
||||
useNavToActivePathMapper('inbox');
|
||||
const notificationsSelected = useInboxNotificationsSelected();
|
||||
|
||||
|
|
@ -53,7 +56,7 @@ export function Inbox() {
|
|||
<Box grow="Yes" gap="300">
|
||||
<Box grow="Yes">
|
||||
<Text size="H4" truncate>
|
||||
Inbox
|
||||
{t('Inbox.inbox')}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -71,7 +74,7 @@ export function Inbox() {
|
|||
</Avatar>
|
||||
<Box as="span" grow="Yes">
|
||||
<Text as="span" size="Inherit" truncate>
|
||||
Notifications
|
||||
{t('Inbox.notifications')}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
config,
|
||||
} from 'folds';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RoomTopicEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { MatrixClient, MatrixError, Room } from 'matrix-js-sdk';
|
||||
|
|
@ -159,6 +160,7 @@ function InviteCard({
|
|||
onNavigate,
|
||||
hideAvatar,
|
||||
}: InviteCardProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const userId = mx.getSafeUserId();
|
||||
|
||||
|
|
@ -200,21 +202,21 @@ function InviteCard({
|
|||
{invite.isEncrypted && (
|
||||
<Box shrink="No" alignItems="Center" justifyContent="Center">
|
||||
<Badge variant="Success" fill="Solid" size="400" radii="300">
|
||||
<Text size="L400">Encrypted</Text>
|
||||
<Text size="L400">{t('Inbox.encrypted')}</Text>
|
||||
</Badge>
|
||||
</Box>
|
||||
)}
|
||||
{invite.isDirect && (
|
||||
<Box shrink="No" alignItems="Center" justifyContent="Center">
|
||||
<Badge variant="Primary" fill="Solid" size="400" radii="300">
|
||||
<Text size="L400">Direct Message</Text>
|
||||
<Text size="L400">{t('Inbox.direct_message')}</Text>
|
||||
</Badge>
|
||||
</Box>
|
||||
)}
|
||||
{invite.isSpace && (
|
||||
<Box shrink="No" alignItems="Center" justifyContent="Center">
|
||||
<Badge variant="Secondary" fill="Soft" size="400" radii="300">
|
||||
<Text size="L400">Space</Text>
|
||||
<Text size="L400">{t('Inbox.space')}</Text>
|
||||
</Badge>
|
||||
</Box>
|
||||
)}
|
||||
|
|
@ -290,7 +292,7 @@ function InviteCard({
|
|||
disabled={joining || leaving}
|
||||
before={leaving ? <Spinner variant="Secondary" size="100" /> : undefined}
|
||||
>
|
||||
<Text size="B300">Decline</Text>
|
||||
<Text size="B300">{t('Inbox.decline')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={join}
|
||||
|
|
@ -302,7 +304,7 @@ function InviteCard({
|
|||
disabled={joining || leaving}
|
||||
before={joining ? <Spinner variant="Success" fill="Soft" size="100" /> : undefined}
|
||||
>
|
||||
<Text size="B300">Accept</Text>
|
||||
<Text size="B300">{t('Inbox.accept')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -311,7 +313,7 @@ function InviteCard({
|
|||
<Box gap="200" alignItems="Baseline">
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" priority="300">
|
||||
From: <b>{invite.senderId}</b>
|
||||
{t('Inbox.from')}<b>{invite.senderId}</b>
|
||||
</Text>
|
||||
</Box>
|
||||
{typeof invite.inviteTs === 'number' && invite.inviteTs !== 0 && (
|
||||
|
|
@ -328,7 +330,7 @@ function InviteCard({
|
|||
</Box>
|
||||
{invite.reason && (
|
||||
<Text size="T200" priority="300">
|
||||
Reason: {invite.reason}
|
||||
{t('Inbox.reason_label')}{invite.reason}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -355,6 +357,7 @@ function InviteFilters({
|
|||
unknownInvites,
|
||||
spamInvites,
|
||||
}: InviteFiltersProps) {
|
||||
const { t } = useTranslation();
|
||||
const isKnown = filter === InviteFilter.Known;
|
||||
const isUnknown = filter === InviteFilter.Unknown;
|
||||
const isSpam = filter === InviteFilter.Spam;
|
||||
|
|
@ -375,7 +378,7 @@ function InviteFilters({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="T200">Primary</Text>
|
||||
<Text size="T200">{t('Inbox.primary')}</Text>
|
||||
</Chip>
|
||||
<Chip
|
||||
variant={isUnknown ? 'Warning' : 'Surface'}
|
||||
|
|
@ -391,7 +394,7 @@ function InviteFilters({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="T200">Public</Text>
|
||||
<Text size="T200">{t('Inbox.public')}</Text>
|
||||
</Chip>
|
||||
<Chip
|
||||
variant={isSpam ? 'Critical' : 'Surface'}
|
||||
|
|
@ -407,7 +410,7 @@ function InviteFilters({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="T200">Spam</Text>
|
||||
<Text size="T200">{t('Inbox.spam')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
);
|
||||
|
|
@ -427,9 +430,10 @@ function KnownInvites({
|
|||
hour24Clock,
|
||||
dateFormatString,
|
||||
}: KnownInvitesProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box direction="Column" gap="200">
|
||||
<Text size="H4">Primary</Text>
|
||||
<Text size="H4">{t('Inbox.primary')}</Text>
|
||||
{invites.length > 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
{invites.map((invite) => (
|
||||
|
|
@ -449,8 +453,8 @@ function KnownInvites({
|
|||
<PageHeroSection>
|
||||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Mail} />}
|
||||
title="No Invites"
|
||||
subTitle="When someone you share a room with sends you an invite, it’ll show up here."
|
||||
title={t('Inbox.no_invites')}
|
||||
subTitle={t('Inbox.no_invites_known_desc')}
|
||||
/>
|
||||
</PageHeroSection>
|
||||
</PageHeroEmpty>
|
||||
|
|
@ -473,6 +477,7 @@ function UnknownInvites({
|
|||
hour24Clock,
|
||||
dateFormatString,
|
||||
}: UnknownInvitesProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
|
||||
const [declineAllStatus, declineAll] = useAsyncCallback(
|
||||
|
|
@ -488,7 +493,7 @@ function UnknownInvites({
|
|||
return (
|
||||
<Box direction="Column" gap="200">
|
||||
<Box gap="200" justifyContent="SpaceBetween" alignItems="Center">
|
||||
<Text size="H4">Public</Text>
|
||||
<Text size="H4">{t('Inbox.public')}</Text>
|
||||
<Box>
|
||||
{invites.length > 0 && (
|
||||
<Chip
|
||||
|
|
@ -498,7 +503,7 @@ function UnknownInvites({
|
|||
disabled={declining}
|
||||
radii="Pill"
|
||||
>
|
||||
<Text size="T200">Decline All</Text>
|
||||
<Text size="T200">{t('Inbox.decline_all')}</Text>
|
||||
</Chip>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -522,8 +527,8 @@ function UnknownInvites({
|
|||
<PageHeroSection>
|
||||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Info} />}
|
||||
title="No Invites"
|
||||
subTitle="Invites from people outside your rooms will appear here."
|
||||
title={t('Inbox.no_invites')}
|
||||
subTitle={t('Inbox.no_invites_unknown_desc')}
|
||||
/>
|
||||
</PageHeroSection>
|
||||
</PageHeroEmpty>
|
||||
|
|
@ -546,6 +551,7 @@ function SpamInvites({
|
|||
hour24Clock,
|
||||
dateFormatString,
|
||||
}: SpamInvitesProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const [showInvites, setShowInvites] = useState(false);
|
||||
|
||||
|
|
@ -585,7 +591,7 @@ function SpamInvites({
|
|||
|
||||
return (
|
||||
<Box direction="Column" gap="200">
|
||||
<Text size="H4">Spam</Text>
|
||||
<Text size="H4">{t('Inbox.spam')}</Text>
|
||||
{invites.length > 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
<SequenceCard
|
||||
|
|
@ -597,8 +603,8 @@ function SpamInvites({
|
|||
<PageHeroSection>
|
||||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Warning} />}
|
||||
title={`${invites.length} Spam Invites`}
|
||||
subTitle="Some of the following invites may contain harmful content or have been sent by banned users."
|
||||
title={t('Inbox.spam_invites_count', { count: invites.length })}
|
||||
subTitle={t('Inbox.spam_invites_desc')}
|
||||
>
|
||||
<Box direction="Row" gap="200" justifyContent="Center" wrap="Wrap">
|
||||
<Button
|
||||
|
|
@ -611,7 +617,7 @@ function SpamInvites({
|
|||
disabled={loading}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
Decline All
|
||||
{t('Inbox.decline_all')}
|
||||
</Text>
|
||||
</Button>
|
||||
{reportRoomSupported && reportAllStatus.status !== AsyncStatus.Success && (
|
||||
|
|
@ -625,7 +631,7 @@ function SpamInvites({
|
|||
disabled={loading}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
Report All
|
||||
{t('Inbox.report_all')}
|
||||
</Text>
|
||||
</Button>
|
||||
)}
|
||||
|
|
@ -640,7 +646,7 @@ function SpamInvites({
|
|||
before={blocking && <Spinner size="100" variant="Secondary" fill="Solid" />}
|
||||
>
|
||||
<Text size="B300" truncate>
|
||||
Block All
|
||||
{t('Inbox.block_all')}
|
||||
</Text>
|
||||
</Button>
|
||||
)}
|
||||
|
|
@ -658,7 +664,7 @@ function SpamInvites({
|
|||
}
|
||||
onClick={() => setShowInvites(!showInvites)}
|
||||
>
|
||||
<Text size="B300">{showInvites ? 'Hide All' : 'View All'}</Text>
|
||||
<Text size="B300">{showInvites ? t('Inbox.hide_all') : t('Inbox.view_all')}</Text>
|
||||
</Button>
|
||||
</PageHero>
|
||||
</PageHeroSection>
|
||||
|
|
@ -681,8 +687,8 @@ function SpamInvites({
|
|||
<PageHeroSection>
|
||||
<PageHero
|
||||
icon={<Icon size="600" src={Icons.Warning} />}
|
||||
title="No Spam Invites"
|
||||
subTitle="Invites detected as spam appear here."
|
||||
title={t('Inbox.no_spam_invites')}
|
||||
subTitle={t('Inbox.no_spam_invites_desc')}
|
||||
/>
|
||||
</PageHeroSection>
|
||||
</PageHeroEmpty>
|
||||
|
|
@ -692,6 +698,7 @@ function SpamInvites({
|
|||
}
|
||||
|
||||
export function Invites() {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const { navigateRoom, navigateSpace } = useRoomNavigate();
|
||||
|
|
@ -763,7 +770,7 @@ export function Invites() {
|
|||
<Box alignItems="Center" gap="200">
|
||||
{screenSize !== ScreenSize.Mobile && <Icon size="400" src={Icons.Mail} />}
|
||||
<Text size="H3" truncate>
|
||||
Invites
|
||||
{t('Inbox.invites')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box grow="Yes" basis="No" />
|
||||
|
|
@ -776,7 +783,7 @@ export function Invites() {
|
|||
<Box ref={containerRef} direction="Column" gap="600">
|
||||
<Box direction="Column" gap="100">
|
||||
<span data-spacing-node />
|
||||
<Text size="L400">Filter</Text>
|
||||
<Text size="L400">{t('Inbox.filter')}</Text>
|
||||
<InviteFilters
|
||||
filter={filter}
|
||||
onFilter={setFilter}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
toRem,
|
||||
} from 'folds';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
INotification,
|
||||
INotificationsResponse,
|
||||
|
|
@ -222,6 +223,7 @@ function RoomNotificationsGroupComp({
|
|||
hour24Clock,
|
||||
dateFormatString,
|
||||
}: RoomNotificationsGroupProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||
|
|
@ -438,7 +440,7 @@ function RoomNotificationsGroupComp({
|
|||
onClick={handleMarkAsRead}
|
||||
before={<Icon size="100" src={Icons.CheckTwice} />}
|
||||
>
|
||||
<Text size="T200">Mark as Read</Text>
|
||||
<Text size="T200">{t('Inbox.mark_as_read')}</Text>
|
||||
</Chip>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -524,7 +526,7 @@ function RoomNotificationsGroupComp({
|
|||
variant="Secondary"
|
||||
radii="400"
|
||||
>
|
||||
<Text size="T200">Open</Text>
|
||||
<Text size="T200">{t('Inbox.open')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -562,6 +564,7 @@ const useNotificationsSearchParams = (
|
|||
const DEFAULT_REFRESH_MS = 7000;
|
||||
|
||||
export function Notifications() {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
|
||||
|
|
@ -652,7 +655,7 @@ export function Notifications() {
|
|||
<Box alignItems="Center" gap="200">
|
||||
{screenSize !== ScreenSize.Mobile && <Icon size="400" src={Icons.Message} />}
|
||||
<Text size="H3" truncate>
|
||||
Notification Messages
|
||||
{t('Inbox.notification_messages')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box grow="Yes" basis="No" />
|
||||
|
|
@ -666,7 +669,7 @@ export function Notifications() {
|
|||
<Box direction="Column" gap="200">
|
||||
<Box ref={scrollTopAnchorRef} direction="Column" gap="100">
|
||||
<span data-spacing-node />
|
||||
<Text size="L400">Filter</Text>
|
||||
<Text size="L400">{t('Inbox.filter')}</Text>
|
||||
<Box gap="200">
|
||||
<Chip
|
||||
onClick={() => setOnlyHighlighted(false)}
|
||||
|
|
@ -675,7 +678,7 @@ export function Notifications() {
|
|||
before={!onlyHighlight && <Icon size="100" src={Icons.Check} />}
|
||||
outlined
|
||||
>
|
||||
<Text size="T200">All Notifications</Text>
|
||||
<Text size="T200">{t('Inbox.all_notifications')}</Text>
|
||||
</Chip>
|
||||
<Chip
|
||||
onClick={() => setOnlyHighlighted(true)}
|
||||
|
|
@ -684,7 +687,7 @@ export function Notifications() {
|
|||
before={onlyHighlight && <Icon size="100" src={Icons.Check} />}
|
||||
outlined
|
||||
>
|
||||
<Text size="T200">Highlighted</Text>
|
||||
<Text size="T200">{t('Inbox.highlighted')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -699,7 +702,7 @@ export function Notifications() {
|
|||
radii="Pill"
|
||||
outlined
|
||||
size="300"
|
||||
aria-label="Scroll to Top"
|
||||
aria-label={t('Inbox.scroll_to_top')}
|
||||
>
|
||||
<Icon src={Icons.ChevronTop} size="300" />
|
||||
</IconButton>
|
||||
|
|
@ -752,9 +755,9 @@ export function Notifications() {
|
|||
direction="Column"
|
||||
gap="200"
|
||||
>
|
||||
<Text>No Notifications</Text>
|
||||
<Text>{t('Inbox.no_notifications')}</Text>
|
||||
<Text size="T200">
|
||||
You don't have any new notifications to display yet.
|
||||
{t('Inbox.no_notifications_desc')}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Icon, Icons } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import {
|
||||
SidebarAvatar,
|
||||
|
|
@ -21,6 +22,7 @@ import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
|||
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
|
||||
|
||||
export function InboxTab() {
|
||||
const { t } = useTranslation();
|
||||
const screenSize = useScreenSizeContext();
|
||||
const navigate = useNavigate();
|
||||
const navToActivePath = useAtomValue(useNavToActivePathAtom());
|
||||
|
|
@ -45,7 +47,7 @@ export function InboxTab() {
|
|||
|
||||
return (
|
||||
<SidebarItem active={inboxSelected}>
|
||||
<SidebarItemTooltip tooltip="Inbox">
|
||||
<SidebarItemTooltip tooltip={t('Inbox.inbox')}>
|
||||
{(triggerRef) => (
|
||||
<SidebarAvatar as="button" ref={triggerRef} outlined onClick={handleInboxClick}>
|
||||
<Icon src={Icons.Inbox} filled={inboxSelected} />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Badge, color, Icon, Icons, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
SidebarAvatar,
|
||||
SidebarItem,
|
||||
|
|
@ -19,6 +20,7 @@ import { Modal500 } from '../../../components/Modal500';
|
|||
import { Settings, SettingsPages } from '../../../features/settings';
|
||||
|
||||
function UnverifiedIndicator() {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
|
||||
const crypto = mx.getCrypto();
|
||||
|
|
@ -49,7 +51,7 @@ function UnverifiedIndicator() {
|
|||
<>
|
||||
{hasUnverified && (
|
||||
<SidebarItem active={settings} className={css.UnverifiedTab}>
|
||||
<SidebarItemTooltip tooltip={unverified ? 'Unverified Device' : 'Unverified Devices'}>
|
||||
<SidebarItemTooltip tooltip={unverified ? t('Inbox.unverified_device') : t('Inbox.unverified_devices')}>
|
||||
{(triggerRef) => (
|
||||
<SidebarAvatar
|
||||
className={unverified ? css.UnverifiedAvatar : css.UnverifiedOtherAvatar}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue