Fix code style

This commit is contained in:
Dylan 2022-07-14 20:02:55 +09:30
parent 3668342ca7
commit 41ff8db2f5
59 changed files with 689 additions and 704 deletions

View file

@ -2,25 +2,24 @@ import React from 'react';
import PropTypes from 'prop-types';
import './ConfirmDialog.scss';
import { useTranslation } from 'react-i18next';
import { openReusableDialog } from '../../../client/action/navigation';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ConfirmDialog({
desc, actionTitle, actionType, onComplete,
}) {
const { t } = useTranslation();
return (
<div className="confirm-dialog">
<Text>{desc}</Text>
<div className="confirm-dialog__btn">
<Button variant={actionType} onClick={() => onComplete(true)}>{actionTitle}</Button>
<Button onClick={() => onComplete(false)}>{t("Molecules.ConfirmDialog.cancel")}</Button>
<Button onClick={() => onComplete(false)}>{t('Molecules.ConfirmDialog.cancel')}</Button>
</div>
</div>
);

View file

@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import cons from '../../../client/state/cons';
@ -8,8 +9,7 @@ import Dialog from './Dialog';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ReusableDialog() {
const [isOpen, setIsOpen] = useState(false);
@ -43,7 +43,7 @@ function ReusableDialog() {
title={data?.title || ''}
onAfterClose={handleAfterClose}
onRequestClose={handleRequestClose}
contentOptions={<IconButton src={CrossIC} onClick={handleRequestClose} tooltip={t("Molecules.ReusableDialog.close_tooltip")} />}
contentOptions={<IconButton src={CrossIC} onClick={handleRequestClose} tooltip={t('Molecules.ReusableDialog.close_tooltip')} />}
invisibleScroll
>
{data?.render(handleRequestClose) || <div />}

View file

@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './FollowingMembers.scss';
import { Trans } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { openReadReceipts } from '../../../client/action/navigation';
@ -11,15 +12,10 @@ import Text from '../../atoms/text/Text';
import RawIcon from '../../atoms/system-icons/RawIcon';
import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
import { getUsersActionJsx } from '../../organisms/room/common';
import { twemojify } from '../../../util/twemojify';
import '../../i18n';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { Trans } from 'react-i18next';
import { getUserDisplayName } from '../../../util/matrixUtil';
function FollowingMembers({ roomTimeline }) {
@ -65,9 +61,9 @@ function FollowingMembers({ roomTimeline }) {
user_one: twemojify(getUserDisplayName(room, filteredM?.[0])),
user_two: twemojify(getUserDisplayName(room, filteredM?.[1])),
user_three: twemojify(getUserDisplayName(room, filteredM?.[2])),
other_count: filteredM.length - 3
other_count: filteredM.length - 3,
}}
components={{bold: <b/>}}
components={{ bold: <b /> }}
/>
</Text>
</button>

View file

@ -2,14 +2,14 @@ import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
import './ImageUpload.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import Spinner from '../../atoms/spinner/Spinner';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ImageUpload({
text, bgColor, imageSrc, onUpload, onRequestRemove,
@ -58,7 +58,7 @@ function ImageUpload({
size="large"
/>
<div className={`img-upload__process ${uploadPromise === null ? ' img-upload__process--stopped' : ''}`}>
{uploadPromise === null && <Text variant="b3" weight="bold">{t("Molecules.ImageUpload.prompt")}</Text>}
{uploadPromise === null && <Text variant="b3" weight="bold">{t('Molecules.ImageUpload.prompt')}</Text>}
{uploadPromise !== null && <Spinner size="small" />}
</div>
</button>
@ -68,7 +68,7 @@ function ImageUpload({
type="button"
onClick={uploadPromise === null ? onRequestRemove : cancelUpload}
>
<Text variant="b3">{uploadPromise ? t("Molecules.ImageUpload.cancel") : t("Molecules.ImageUpload.remove")}</Text>
<Text variant="b3">{uploadPromise ? t('Molecules.ImageUpload.cancel') : t('Molecules.ImageUpload.remove')}</Text>
</button>
)}
<input onChange={uploadImage} style={{ display: 'none' }} ref={uploadImageRef} type="file" />

View file

@ -3,6 +3,7 @@ import './ExportE2ERoomKeys.scss';
import FileSaver from 'file-saver';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { encryptMegolmKeyFile } from '../../../util/cryptE2ERoomKeys';
@ -14,8 +15,7 @@ import Spinner from '../../atoms/spinner/Spinner';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ExportE2ERoomKeys() {
const isMountStore = useStore();
@ -34,14 +34,14 @@ function ExportE2ERoomKeys() {
if (password !== confirmPasswordRef.current.value) {
setStatus({
isOngoing: false,
msg: t("Molecules.ExportE2ERoomKeys.password_does_not_match"),
msg: t('Molecules.ExportE2ERoomKeys.password_does_not_match'),
type: cons.status.ERROR,
});
return;
}
setStatus({
isOngoing: true,
msg: t("Molecules.ExportE2ERoomKeys.getting_keys"),
msg: t('Molecules.ExportE2ERoomKeys.getting_keys'),
type: cons.status.IN_FLIGHT,
});
try {
@ -49,7 +49,7 @@ function ExportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: true,
msg: t("Molecules.ExportE2ERoomKeys.encrypting_keys"),
msg: t('Molecules.ExportE2ERoomKeys.encrypting_keys'),
type: cons.status.IN_FLIGHT,
});
}
@ -61,7 +61,7 @@ function ExportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: false,
msg: t("Molecules.ExportE2ERoomKeys.export_success"),
msg: t('Molecules.ExportE2ERoomKeys.export_success'),
type: cons.status.SUCCESS,
});
}
@ -69,7 +69,7 @@ function ExportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: false,
msg: e.friendlyText || t("Molecules.ExportE2ERoomKeys.export_failed"),
msg: e.friendlyText || t('Molecules.ExportE2ERoomKeys.export_failed'),
type: cons.status.ERROR,
});
}
@ -88,7 +88,7 @@ function ExportE2ERoomKeys() {
<form className="export-e2e-room-keys__form" onSubmit={(e) => { e.preventDefault(); exportE2ERoomKeys(); }}>
<Input forwardRef={passwordRef} type="password" placeholder="Password" required />
<Input forwardRef={confirmPasswordRef} type="password" placeholder="Confirm password" required />
<Button disabled={status.isOngoing} variant="primary" type="submit">{t("Molecules.ExportE2ERoomKeys.button_text")}</Button>
<Button disabled={status.isOngoing} variant="primary" type="submit">{t('Molecules.ExportE2ERoomKeys.button_text')}</Button>
</form>
{ status.type === cons.status.IN_FLIGHT && (
<div className="import-e2e-room-keys__process">

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from 'react';
import './ImportE2ERoomKeys.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { decryptMegolmKeyFile } from '../../../util/cryptE2ERoomKeys';
@ -15,8 +16,7 @@ import CirclePlusIC from '../../../../public/res/ic/outlined/circle-plus.svg';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ImportE2ERoomKeys() {
const isMountStore = useStore();
@ -37,7 +37,7 @@ function ImportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: true,
msg: t("Molecules.ImportE2ERoomKeys.decrypting_file"),
msg: t('Molecules.ImportE2ERoomKeys.decrypting_file'),
type: cons.status.IN_FLIGHT,
});
}
@ -46,7 +46,7 @@ function ImportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: true,
msg: t("Molecules.ImportE2ERoomKeys.decrypting_messages"),
msg: t('Molecules.ImportE2ERoomKeys.decrypting_messages'),
type: cons.status.IN_FLIGHT,
});
}
@ -54,7 +54,7 @@ function ImportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: false,
msg: t("Molecules.ImportE2ERoomKeys.import_success"),
msg: t('Molecules.ImportE2ERoomKeys.import_success'),
type: cons.status.SUCCESS,
});
inputRef.current.value = null;
@ -64,7 +64,7 @@ function ImportE2ERoomKeys() {
if (isMountStore.getItem()) {
setStatus({
isOngoing: false,
msg: e.friendlyText || t("Molecules.ImportE2ERoomKeys.import_failed"),
msg: e.friendlyText || t('Molecules.ImportE2ERoomKeys.import_failed'),
type: cons.status.ERROR,
});
}
@ -119,9 +119,9 @@ function ImportE2ERoomKeys() {
<Text>{keyFile.name}</Text>
</div>
)}
{keyFile === null && <Button onClick={() => inputRef.current.click()}>{t("Molecules.ImportE2ERoomKeys.import_keys_button")}</Button>}
{keyFile === null && <Button onClick={() => inputRef.current.click()}>{t('Molecules.ImportE2ERoomKeys.import_keys_button')}</Button>}
<Input forwardRef={passwordRef} type="password" placeholder="Password" required />
<Button disabled={status.isOngoing} variant="primary" type="submit">{t("Molecules.ImportE2ERoomKeys.decrypt_button")}</Button>
<Button disabled={status.isOngoing} variant="primary" type="submit">{t('Molecules.ImportE2ERoomKeys.decrypt_button')}</Button>
</form>
{ status.type === cons.status.IN_FLIGHT && (
<div className="import-e2e-room-keys__process">

View file

@ -4,6 +4,7 @@ import './Media.scss';
import encrypt from 'browser-encrypt-attachment';
import { useTranslation } from 'react-i18next';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
import Spinner from '../../atoms/spinner/Spinner';
@ -12,8 +13,7 @@ import DownloadSVG from '../../../../public/res/ic/outlined/download.svg';
import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
// https://github.com/matrix-org/matrix-react-sdk/blob/a9e28db33058d1893d964ec96cd247ecc3d92fc3/src/utils/blobs.ts#L73
const ALLOWED_BLOB_MIMETYPES = [
@ -99,7 +99,7 @@ function FileHeader({
external && (
<IconButton
size="extra-small"
tooltip={t("Molecules.Media.open_new_tab")}
tooltip={t('Molecules.Media.open_new_tab')}
src={ExternalSVG}
onClick={() => window.open(url || link)}
/>
@ -108,7 +108,7 @@ function FileHeader({
<a href={url || link} download={name} target="_blank" rel="noreferrer">
<IconButton
size="extra-small"
tooltip= {t("Molecules.Media.download")}
tooltip={t('Molecules.Media.download')}
src={DownloadSVG}
onClick={handleDownload}
/>
@ -156,7 +156,6 @@ function Image({
}) {
const [url, setUrl] = useState(null);
useEffect(() => {
let unmounted = false;
async function fetchUrl() {
@ -217,7 +216,7 @@ function Audio({
<FileHeader name={name} link={file !== null ? url : url || link} type={type} external />
<div className="audio-container">
{ url === null && isLoading && <Spinner size="small" /> }
{ url === null && !isLoading && <IconButton onClick={handlePlayAudio} tooltip={t("Molecules.Media.play_audio")} src={PlaySVG} />}
{ url === null && !isLoading && <IconButton onClick={handlePlayAudio} tooltip={t('Molecules.Media.play_audio')} src={PlaySVG} />}
{ url !== null && (
/* eslint-disable-next-line jsx-a11y/media-has-caption */
<audio autoPlay controls>
@ -284,7 +283,7 @@ function Video({
className="video-container"
>
{ url === null && isLoading && <Spinner size="small" /> }
{ url === null && !isLoading && <IconButton onClick={handlePlayVideo} tooltip={t("Molecules.Media.play_video")} src={PlaySVG} />}
{ url === null && !isLoading && <IconButton onClick={handlePlayVideo} tooltip={t('Molecules.Media.play_video')} src={PlaySVG} />}
{ url !== null && (
/* eslint-disable-next-line jsx-a11y/media-has-caption */
<video autoPlay controls poster={thumbUrl}>

View file

@ -5,6 +5,7 @@ import React, {
import PropTypes from 'prop-types';
import './Message.scss';
import { useTranslation, Trans } from 'react-i18next';
import { getShortcodeToCustomEmoji } from '../../organisms/emoji-board/custom-emoji';
import { twemojify } from '../../../util/twemojify';
@ -38,10 +39,7 @@ import BinIC from '../../../../public/res/ic/outlined/bin.svg';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { Trans } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function PlaceholderMessage() {
return (
@ -256,7 +254,7 @@ const MessageBody = React.memo(({
)}
{ content }
</div>
{ isEdited && <Text className="message__body-edited" variant="b3"><Trans i18nKey={"Molecules.Message.edited"}/></Text>}
{ isEdited && <Text className="message__body-edited" variant="b3"><Trans i18nKey="Molecules.Message.edited" /></Text>}
</div>
);
});
@ -297,14 +295,14 @@ function MessageEdit({ body, onSave, onCancel }) {
forwardRef={editInputRef}
onKeyDown={handleKeyDown}
value={body}
placeholder={t("Molecules.Message.edit_placeholder")}
placeholder={t('Molecules.Message.edit_placeholder')}
required
resizable
autoFocus
/>
<div className="message__edit-btns">
<Button type="submit" variant="primary">{t("common.save")}</Button>
<Button onClick={onCancel}>{t("common.cancel")}</Button>
<Button type="submit" variant="primary">{t('common.save')}</Button>
<Button onClick={onCancel}>{t('common.cancel')}</Button>
</div>
</form>
);
@ -351,7 +349,6 @@ function pickEmoji(e, roomId, eventId, roomTimeline) {
function genReactionMsg(userIds, reaction) {
console.log(reaction);
return (
<>
<Trans
i18nKey="Molecules.Message.user_reacted"
values={{
@ -361,10 +358,8 @@ function genReactionMsg(userIds, reaction) {
user_three: getUsername(userIds?.[2]),
other_count: userIds.length - 3,
}}
components={{bold: <b/>, emoji: reaction}}
components={{ bold: <b />, emoji: reaction }}
/>
</>
);
}
@ -520,6 +515,8 @@ const MessageOptions = React.memo(({
const canIRedact = room.currentState.hasSufficientPowerLevelFor('redact', myPowerlevel);
const canSendReaction = room.currentState.maySendEvent('m.reaction', mx.getUserId());
const { t } = useTranslation();
return (
<div className="message__options">
{canSendReaction && (
@ -527,38 +524,38 @@ const MessageOptions = React.memo(({
onClick={(e) => pickEmoji(e, roomId, mEvent.getId(), roomTimeline)}
src={EmojiAddIC}
size="extra-small"
tooltip={t("Molecules.Message.add_reaction_tooltip")}
tooltip={t('Molecules.Message.add_reaction_tooltip')}
/>
)}
<IconButton
onClick={() => reply()}
src={ReplyArrowIC}
size="extra-small"
tooltip={t("Molecules.Message.reply_tooltip")}
tooltip={t('Molecules.Message.reply_tooltip')}
/>
{(senderId === mx.getUserId() && !isMedia(mEvent)) && (
<IconButton
onClick={() => edit(true)}
src={PencilIC}
size="extra-small"
tooltip={t("Molecules.Message.edit_tooltip")}
tooltip={t('Molecules.Message.edit_tooltip')}
/>
)}
<ContextMenu
content={() => (
<>
<MenuHeader>{t("Molecules.Message.options_header")}</MenuHeader>
<MenuHeader>{t('Molecules.Message.options_header')}</MenuHeader>
<MenuItem
iconSrc={TickMarkIC}
onClick={() => openReadReceipts(roomId, roomTimeline.getEventReaders(mEvent))}
>
{t("Molecules.Message.read_receipts")}
{t('Molecules.Message.read_receipts')}
</MenuItem>
<MenuItem
iconSrc={CmdIC}
onClick={() => handleOpenViewSource(mEvent, roomTimeline)}
>
{t("Molecules.Message.view_source")}
{t('Molecules.Message.view_source')}
</MenuItem>
{(canIRedact || senderId === mx.getUserId()) && (
<>
@ -568,9 +565,9 @@ const MessageOptions = React.memo(({
iconSrc={BinIC}
onClick={async () => {
const isConfirmed = await confirmDialog(
t("Molecules.Message.delete_message_prompt"),
t("Molecules.Message.delete_message_confirmation"),
t("Molecules.Message.delete_message_button"),
t('Molecules.Message.delete_message_prompt'),
t('Molecules.Message.delete_message_confirmation'),
t('Molecules.Message.delete_message_button'),
'danger',
);
if (!isConfirmed) return;
@ -588,7 +585,7 @@ const MessageOptions = React.memo(({
onClick={toggleMenu}
src={VerticalMenuIC}
size="extra-small"
tooltip={t("Molecules.Message.options_tooltip")}
tooltip={t('Molecules.Message.options_tooltip')}
/>
)}
/>

View file

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import './PopupWindow.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import Text from '../../atoms/text/Text';
@ -13,8 +14,7 @@ import RawModal from '../../atoms/modal/RawModal';
import ChevronLeftIC from '../../../../public/res/ic/outlined/chevron-left.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function PWContentSelector({
selected, variant, iconSrc,
@ -74,7 +74,7 @@ function PopupWindow({
{haveDrawer && (
<div className="pw__drawer">
<Header>
<IconButton size="small" src={ChevronLeftIC} onClick={onRequestClose} tooltip={t("Molecules.PopupWindow.close_tooltip")}/>
<IconButton size="small" src={ChevronLeftIC} onClick={onRequestClose} tooltip={t('Molecules.PopupWindow.close_tooltip')} />
<TitleWrapper>
{
typeof title === 'string'

View file

@ -2,13 +2,13 @@ import React from 'react';
import PropTypes from 'prop-types';
import './PowerLevelSelector.scss';
import { useTranslation } from 'react-i18next';
import IconButton from '../../atoms/button/IconButton';
import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
import CheckIC from '../../../../public/res/ic/outlined/check.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function PowerLevelSelector({
value, max, onSelect,
@ -30,7 +30,7 @@ function PowerLevelSelector({
defaultValue={value}
type="number"
name="power-level"
placeholder={t("Molecules.PowerLevelIndicator.placeholder")}
placeholder={t('Molecules.PowerLevelIndicator.placeholder')}
max={max}
autoComplete="off"
required

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomAliases.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { Debounce } from '../../../util/common';
@ -17,14 +18,12 @@ import SettingTile from '../setting-tile/SettingTile';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function useValidate(hsString) {
const [debounce] = useState(new Debounce());
const [validate, setValidate] = useState({ alias: null, status: cons.status.PRE_FLIGHT });
const { t } = useTranslation();
const setValidateToDefault = () => {
@ -43,7 +42,7 @@ function useValidate(hsString) {
setValidate({
alias: null,
status: cons.status.ERROR,
msg: t("Molecules.RoomAliases.invalid_characters")
msg: t('Molecules.RoomAliases.invalid_characters'),
});
return false;
}
@ -65,7 +64,7 @@ function useValidate(hsString) {
setValidate({
alias,
status: cons.status.IN_FLIGHT,
msg: t("Molecules.RoomAliases.validating_alias", {alias: alias}),
msg: t('Molecules.RoomAliases.validating_alias', { alias }),
});
const isValid = await isRoomAliasAvailable(alias);
@ -76,7 +75,7 @@ function useValidate(hsString) {
return {
alias,
status: isValid ? cons.status.SUCCESS : cons.status.ERROR,
msg: t( isValid ? "Molecules.RoomAliases.alias_available": "Molecules.RoomAliases.alias_unavailable", {alias: alias}),
msg: t(isValid ? 'Molecules.RoomAliases.alias_available' : 'Molecules.RoomAliases.alias_unavailable', { alias }),
};
});
}, 600)();
@ -233,7 +232,7 @@ function RoomAliases({ roomId }) {
const handleDeleteAlias = async (alias) => {
try {
setDeleteAlias({ alias, status: cons.status.IN_FLIGHT, msg: t("Molecules.RoomAliases.deleting_alias")});
setDeleteAlias({ alias, status: cons.status.IN_FLIGHT, msg: t('Molecules.RoomAliases.deleting_alias') });
await mx.deleteAlias(alias);
let { main, published, local } = aliases;
if (published.includes(alias)) {
@ -267,10 +266,10 @@ function RoomAliases({ roomId }) {
return (
<div className="room-aliases__item-btns">
{canPublishAlias && !isMain && <Button onClick={() => handleSetMainAlias(alias)} variant="primary">{t("Molecules.RoomAliases.set_main_alias")}</Button>}
{!isPublished && canPublishAlias && <Button onClick={() => handlePublishAlias(alias)} variant="positive">{t("Molecules.RoomAliases.publish_alias")}</Button>}
{isPublished && canPublishAlias && <Button onClick={() => handleUnPublishAlias(alias)} variant="caution">{t("Molecules.RoomAliases.unpublish_alias")}</Button>}
<Button onClick={() => handleDeleteAlias(alias)} variant="danger">{t("Molecules.RoomAliases.delete_alias")}</Button>
{canPublishAlias && !isMain && <Button onClick={() => handleSetMainAlias(alias)} variant="primary">{t('Molecules.RoomAliases.set_main_alias')}</Button>}
{!isPublished && canPublishAlias && <Button onClick={() => handlePublishAlias(alias)} variant="positive">{t('Molecules.RoomAliases.publish_alias')}</Button>}
{isPublished && canPublishAlias && <Button onClick={() => handleUnPublishAlias(alias)} variant="caution">{t('Molecules.RoomAliases.unpublish_alias')}</Button>}
<Button onClick={() => handleDeleteAlias(alias)} variant="danger">{t('Molecules.RoomAliases.delete_alias')}</Button>
</div>
);
};
@ -286,7 +285,7 @@ function RoomAliases({ roomId }) {
<Checkbox variant="positive" disabled={disabled} isActive={isActive} onToggle={() => handleAliasSelect(alias)} />
<Text>
{alias}
{isMain && <span>{t("Molecules.RoomAliases.main_alias")}</span>}
{isMain && <span>{t('Molecules.RoomAliases.main_alias')}</span>}
</Text>
</div>
{isActive && renderAliasBtns(alias)}
@ -300,8 +299,8 @@ function RoomAliases({ roomId }) {
return (
<div className="room-aliases">
<SettingTile
title={t("Molecules.RoomAliases.publish_to_room_directory.title")}
content={<Text variant="b3">{t(room.isSpaceRoom() ? "Molecules.RoomAliases.publish_to_room_directory.publish_space_message" : "Molecules.RoomAliases.publish_to_room_directory.publish_room_message", {homeserver: hsString})}</Text>}
title={t('Molecules.RoomAliases.publish_to_room_directory.title')}
content={<Text variant="b3">{t(room.isSpaceRoom() ? 'Molecules.RoomAliases.publish_to_room_directory.publish_space_message' : 'Molecules.RoomAliases.publish_to_room_directory.publish_room_message', { homeserver: hsString })}</Text>}
options={(
<Toggle
isActive={isPublic}
@ -312,35 +311,35 @@ function RoomAliases({ roomId }) {
/>
<div className="room-aliases__content">
<MenuHeader>{t("Molecules.RoomAliases.published_addresses.title")}</MenuHeader>
{(aliases.published.length === 0) && <Text className="room-aliases__message">{t("Molecules.RoomAliases.published_addresses.none")}</Text>}
{(aliases.published.length > 0 && !aliases.main) && <Text className="room-aliases__message">{t("Molecules.RoomAliases.published_addresses.no_main_address")}</Text>}
<MenuHeader>{t('Molecules.RoomAliases.published_addresses.title')}</MenuHeader>
{(aliases.published.length === 0) && <Text className="room-aliases__message">{t('Molecules.RoomAliases.published_addresses.none')}</Text>}
{(aliases.published.length > 0 && !aliases.main) && <Text className="room-aliases__message">{t('Molecules.RoomAliases.published_addresses.no_main_address')}</Text>}
{aliases.published.map(renderAlias)}
<Text className="room-aliases__message" variant="b3">
{t(room.isSpaceRoom() ? "Molecules.RoomAliases.published_addresses.message_space" : "Molecules.RoomAliases.published_addresses.message_room")}
{t(room.isSpaceRoom() ? 'Molecules.RoomAliases.published_addresses.message_space' : 'Molecules.RoomAliases.published_addresses.message_room')}
</Text>
</div>
{ isLocalVisible && (
<div className="room-aliases__content">
<MenuHeader>{t("Molecules.RoomAliases.local_addresses.title")}</MenuHeader>
{(aliases.local.length === 0) && <Text className="room-aliases__message">{t("Molecules.RoomAliases.local_addresses.none")}</Text>}
<MenuHeader>{t('Molecules.RoomAliases.local_addresses.title')}</MenuHeader>
{(aliases.local.length === 0) && <Text className="room-aliases__message">{t('Molecules.RoomAliases.local_addresses.none')}</Text>}
{aliases.local.map(renderAlias)}
<Text className="room-aliases__message" variant="b3">
{t(room.isSpaceRoom() ? "Molecules.RoomAliases.local_addresses.message_space" : "Molecules.RoomAliases.local_addresses.message_room" )}
{t(room.isSpaceRoom() ? 'Molecules.RoomAliases.local_addresses.message_space' : 'Molecules.RoomAliases.local_addresses.message_room')}
</Text>
<Text className="room-aliases__form-label" variant="b2">{t("Molecules.RoomAliases.local_addresses.add")}</Text>
<Text className="room-aliases__form-label" variant="b2">{t('Molecules.RoomAliases.local_addresses.add')}</Text>
<form className="room-aliases__form" onSubmit={handleAliasSubmit}>
<div className="room-aliases__input-wrapper">
<Input
name="alias-input"
state={inputState}
onChange={handleAliasChange}
placeholder={t(room.isSpaceRoom() ? "Molecules.RoomAliases.local_addresses.placeholder_space" : "Molecules.RoomAliases.local_addresses.placeholder_room")}
placeholder={t(room.isSpaceRoom() ? 'Molecules.RoomAliases.local_addresses.placeholder_space' : 'Molecules.RoomAliases.local_addresses.placeholder_room')}
required
/>
</div>
<Button variant="primary" type="submit">{t("Molecules.RoomAliases.local_addresses.add_button")}</Button>
<Button variant="primary" type="submit">{t('Molecules.RoomAliases.local_addresses.add_button')}</Button>
</form>
<div className="room-aliases__input-status">
{validate.status === cons.status.SUCCESS && <Text className="room-aliases__valid" variant="b2">{validate.msg}</Text>}
@ -350,7 +349,7 @@ function RoomAliases({ roomId }) {
)}
<div className="room-aliases__content">
<Button onClick={() => setIsLocalVisible(!isLocalVisible)}>
{t(isLocalVisible ? "Molecules.RoomAliases.local_addresses.hide" : "Molecules.RoomAliases.local_addresses.view" )}
{t(isLocalVisible ? 'Molecules.RoomAliases.local_addresses.hide' : 'Molecules.RoomAliases.local_addresses.view')}
</Button>
</div>
</div>

View file

@ -2,6 +2,7 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './RoomEncryption.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
@ -10,8 +11,8 @@ import SettingTile from '../setting-tile/SettingTile';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function RoomEncryption({ roomId }) {
const mx = initMatrix.matrixClient;
@ -24,14 +25,14 @@ function RoomEncryption({ roomId }) {
const handleEncryptionEnable = async () => {
const joinRule = room.getJoinRule();
const confirmMsg1 = t("Molecules.RoomEncryption.encryption_public_room_message");
const confirmMsg2 = t("Molecules.RoomEncryption.encryption_message");
const confirmMsg1 = t('Molecules.RoomEncryption.encryption_public_room_message');
const confirmMsg2 = t('Molecules.RoomEncryption.encryption_message');
const isConfirmed1 = (joinRule === 'public')
? await confirmDialog(t("Molecules.RoomEncryption.enable_encryption_prompt"), confirmMsg1, t("Molecules.RoomEncryption.continue_button"), 'caution')
? await confirmDialog(t('Molecules.RoomEncryption.enable_encryption_prompt'), confirmMsg1, t('Molecules.RoomEncryption.continue_button'), 'caution')
: true;
if (!isConfirmed1) return;
if (await confirmDialog(t("Molecules.RoomEncryption.enable_encryption_prompt"), confirmMsg2, t("Molecules.RoomEncryption.enable_encryption_button"), 'caution')) {
if (await confirmDialog(t('Molecules.RoomEncryption.enable_encryption_prompt'), confirmMsg2, t('Molecules.RoomEncryption.enable_encryption_button'), 'caution')) {
setIsEncrypted(true);
mx.sendStateEvent(roomId, 'm.room.encryption', {
algorithm: 'm.megolm.v1.aes-sha2',
@ -42,9 +43,9 @@ function RoomEncryption({ roomId }) {
return (
<div className="room-encryption">
<SettingTile
title={t("Molecules.RoomEncryption.enable_room_encryption")}
title={t('Molecules.RoomEncryption.enable_room_encryption')}
content={(
<Text variant="b3">{t("Molecules.RoomEncryption.encryption_cannot_be_disabled")}</Text>
<Text variant="b3">{t('Molecules.RoomEncryption.encryption_cannot_be_disabled')}</Text>
)}
options={(
<Toggle

View file

@ -2,14 +2,14 @@ import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import './RoomHistoryVisibility.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
import RadioButton from '../../atoms/button/RadioButton';
import { MenuItem } from '../../atoms/context-menu/ContextMenu';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const visibility = {
WORLD_READABLE: 'world_readable',
@ -40,7 +40,8 @@ function setHistoryVisibility(roomId, type) {
const mx = initMatrix.matrixClient;
return mx.sendStateEvent(
roomId, 'm.room.history_visibility',
roomId,
'm.room.history_visibility',
{
history_visibility: type,
},
@ -92,7 +93,7 @@ function RoomHistoryVisibility({ roomId }) {
</MenuItem>
))
}
<Text variant="b3">{t("Molecules.RoomHistoryVisibility.changes_only_affect_future")}</Text>
<Text variant="b3">{t('Molecules.RoomHistoryVisibility.changes_only_affect_future')}</Text>
</div>
);
}

View file

@ -4,6 +4,7 @@ import React, {
import PropTypes from 'prop-types';
import './RoomMembers.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import colorMXID from '../../../util/colorMXID';
import { openProfileViewer } from '../../../client/action/navigation';
@ -18,8 +19,7 @@ import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import SegmentedControls from '../../atoms/segmented-controls/SegmentedControls';
import PeopleSelector from '../people-selector/PeopleSelector';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const PER_PAGE_MEMBER = 50;
@ -129,14 +129,14 @@ function RoomMembers({ roomId }) {
const mList = searchMembers ? searchMembers.data : members.slice(0, itemCount);
return (
<div className="room-members">
<MenuHeader>{t("Molecules.RoomMembers.search_title")}</MenuHeader>
<MenuHeader>{t('Molecules.RoomMembers.search_title')}</MenuHeader>
<Input
onChange={handleSearch}
placeholder={t("Molecules.RoomMembers.search_placeholder")}
placeholder={t('Molecules.RoomMembers.search_placeholder')}
autoFocus
/>
<div className="room-members__header">
<MenuHeader>{t("Molecules.RoomMembers.found_members", {count: mList.length})}</MenuHeader>
<MenuHeader>{t('Molecules.RoomMembers.found_members', { count: mList.length })}</MenuHeader>
<SegmentedControls
selected={
(() => {
@ -144,7 +144,7 @@ function RoomMembers({ roomId }) {
return getSegmentIndex[membership];
})()
}
segments={[{ text: t("Molecules.RoomMembers.joined") }, { text: t("Molecules.RoomMembers.invited") }, { text: t("Molecules.RoomMembers.banned") }]}
segments={[{ text: t('Molecules.RoomMembers.joined') }, { text: t('Molecules.RoomMembers.invited') }, { text: t('Molecules.RoomMembers.banned') }]}
onSelect={(index) => {
const memberships = ['join', 'invite', 'ban'];
setMembership(memberships[index]);
@ -167,7 +167,7 @@ function RoomMembers({ roomId }) {
&& (
<div className="room-members__status">
<Text variant="b2">
{searchMembers ? t("Molecules.RoomMembers.invited", {term: searchMembers.term}) : t("Molecules.RoomMembers.no_members")}
{searchMembers ? t('Molecules.RoomMembers.invited', { term: searchMembers.term }) : t('Molecules.RoomMembers.no_members')}
</Text>
</div>
)
@ -176,7 +176,7 @@ function RoomMembers({ roomId }) {
mList.length !== 0
&& members.length > itemCount
&& searchMembers === null
&& <Button onClick={loadMorePeople}>{t("Molecules.RoomMembers.view_more")}</Button>
&& <Button onClick={loadMorePeople}>{t('Molecules.RoomMembers.view_more')}</Button>
}
</div>
</div>

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import './RoomNotification.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
@ -14,8 +15,7 @@ import BellRingIC from '../../../../public/res/ic/outlined/bell-ring.svg';
import BellPingIC from '../../../../public/res/ic/outlined/bell-ping.svg';
import BellOffIC from '../../../../public/res/ic/outlined/bell-off.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const items = [{
iconSrc: BellIC,
@ -117,7 +117,6 @@ function useNotifications(roomId) {
}
function RoomNotification({ roomId }) {
const { t } = useTranslation();
const [activeType, setNotification] = useNotifications(roomId);

View file

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -17,8 +18,7 @@ import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function RoomOptions({ roomId, afterOptionSelect }) {
const mx = initMatrix.matrixClient;
@ -39,9 +39,9 @@ function RoomOptions({ roomId, afterOptionSelect }) {
const handleLeaveClick = async () => {
afterOptionSelect();
const isConfirmed = await confirmDialog(
t("Molecules.RoomOptions.leave.title"),
t("Molecules.RoomOptions.leave.subtitle", {room_name: room.name}),
t("Molecules.RoomOptions.leave.button_text"),
t('Molecules.RoomOptions.leave.title'),
t('Molecules.RoomOptions.leave.subtitle', { room_name: room.name }),
t('Molecules.RoomOptions.leave.button_text'),
'danger',
);
if (!isConfirmed) return;
@ -50,17 +50,17 @@ function RoomOptions({ roomId, afterOptionSelect }) {
return (
<div style={{ maxWidth: '256px' }}>
<MenuHeader>{twemojify(t("Molecules.RoomOptions.title", {room_name: initMatrix.matrixClient.getRoom(roomId)?.name}))}</MenuHeader>
<MenuItem iconSrc={TickMarkIC} onClick={handleMarkAsRead}>{t("Molecules.RoomOptions.mark_as_read")}</MenuItem>
<MenuHeader>{twemojify(t('Molecules.RoomOptions.title', { room_name: initMatrix.matrixClient.getRoom(roomId)?.name }))}</MenuHeader>
<MenuItem iconSrc={TickMarkIC} onClick={handleMarkAsRead}>{t('Molecules.RoomOptions.mark_as_read')}</MenuItem>
<MenuItem
iconSrc={AddUserIC}
onClick={handleInviteClick}
disabled={!canInvite}
>
{t("Molecules.RoomOptions.invite")}
{t('Molecules.RoomOptions.invite')}
</MenuItem>
<MenuItem iconSrc={LeaveArrowIC} variant="danger" onClick={handleLeaveClick}>{t("Molecules.RoomOptions.leave.button_text")}</MenuItem>
<MenuHeader>{t("Molecules.RoomOptions.notifications_heading")}</MenuHeader>
<MenuItem iconSrc={LeaveArrowIC} variant="danger" onClick={handleLeaveClick}>{t('Molecules.RoomOptions.leave.button_text')}</MenuItem>
<MenuHeader>{t('Molecules.RoomOptions.notifications_heading')}</MenuHeader>
<RoomNotification roomId={roomId} />
</div>
);

View file

@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomPermissions.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import { getPowerLabel } from '../../../util/matrixUtil';
import { openReusableContextMenu } from '../../../client/action/navigation';
@ -17,8 +18,7 @@ import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.s
import { useForceUpdate } from '../../hooks/useForceUpdate';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const permissionsInfo = {
users_default: {

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomProfile.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -21,8 +22,7 @@ import { useStore } from '../../hooks/useStore';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function RoomProfile({ roomId }) {
const isMountStore = useStore();
@ -81,7 +81,7 @@ function RoomProfile({ roomId }) {
const newName = roomNameInput.value;
if (newName !== roomName && roomName.trim() !== '') {
setStatus({
msg: t("Molecules.RoomProfile.saving_room_name"),
msg: t('Molecules.RoomProfile.saving_room_name'),
type: cons.status.IN_FLIGHT,
});
await mx.setRoomName(roomId, newName);
@ -92,7 +92,7 @@ function RoomProfile({ roomId }) {
if (newTopic !== roomTopic) {
if (isMountStore.getItem()) {
setStatus({
msg: t("Molecules.RoomProfile.saving_room_topic"),
msg: t('Molecules.RoomProfile.saving_room_topic'),
type: cons.status.IN_FLIGHT,
});
}
@ -101,13 +101,13 @@ function RoomProfile({ roomId }) {
}
if (!isMountStore.getItem()) return;
setStatus({
msg: t("Molecules.RoomProfile.save_success"),
msg: t('Molecules.RoomProfile.save_success'),
type: cons.status.SUCCESS,
});
} catch (err) {
if (!isMountStore.getItem()) return;
setStatus({
msg: err.message || t("Molecules.RoomProfile.save_failed"),
msg: err.message || t('Molecules.RoomProfile.save_failed'),
type: cons.status.ERROR,
});
}
@ -124,9 +124,9 @@ function RoomProfile({ roomId }) {
const handleAvatarUpload = async (url) => {
if (url === null) {
const isConfirmed = await confirmDialog(
t("Molecules.RoomProfile.remove_avatar_title"),
t("Molecules.RoomProfile.remove_avatar_subtitle"),
t("Molecules.RoomProfile.remove_avatar_button"),
t('Molecules.RoomProfile.remove_avatar_title'),
t('Molecules.RoomProfile.remove_avatar_subtitle'),
t('Molecules.RoomProfile.remove_avatar_button'),
'caution',
);
if (isConfirmed) {
@ -137,20 +137,25 @@ function RoomProfile({ roomId }) {
const renderEditNameAndTopic = () => (
<form className="room-profile__edit-form" onSubmit={handleOnSubmit}>
{canChangeName && <Input value={roomName} name="room-name" disabled={status.type === cons.status.IN_FLIGHT} label={t("Molecules.RoomProfile.name_label")} required />}
{canChangeTopic && <Input value={roomTopic} name="room-topic" disabled={status.type === cons.status.IN_FLIGHT} minHeight={100} resizable label={t("Molecules.RoomProfile.topic_label")} />}
{(!canChangeName || !canChangeTopic) && <Text variant="b3">{
room.isSpaceRoom() ?
canChangeName ? "Molecules.RoomProfile.permission_change_space_name" : "Molecules.RoomProfile.permission_change_space_topic" :
canChangeName ? "Molecules.RoomProfile.permission_change_room_name": "Molecules.RoomProfile.permission_change_room_topic"
}</Text>}
{canChangeName && <Input value={roomName} name="room-name" disabled={status.type === cons.status.IN_FLIGHT} label={t('Molecules.RoomProfile.name_label')} required />}
{canChangeTopic && <Input value={roomTopic} name="room-topic" disabled={status.type === cons.status.IN_FLIGHT} minHeight={100} resizable label={t('Molecules.RoomProfile.topic_label')} />}
{(!canChangeName || !canChangeTopic) && (
<Text variant="b3">
{
// eslint-disable-next-line no-nested-ternary
room.isSpaceRoom()
? canChangeName ? 'Molecules.RoomProfile.permission_change_space_name' : 'Molecules.RoomProfile.permission_change_space_topic'
: canChangeName ? 'Molecules.RoomProfile.permission_change_room_name' : 'Molecules.RoomProfile.permission_change_room_topic'
}
</Text>
)}
{ status.type === cons.status.IN_FLIGHT && <Text variant="b2">{status.msg}</Text>}
{ status.type === cons.status.SUCCESS && <Text style={{ color: 'var(--tc-positive-high)' }} variant="b2">{status.msg}</Text>}
{ status.type === cons.status.ERROR && <Text style={{ color: 'var(--tc-danger-high)' }} variant="b2">{status.msg}</Text>}
{ status.type !== cons.status.IN_FLIGHT && (
<div>
<Button type="submit" variant="primary">{t("common.save")}</Button>
<Button onClick={handleCancelEditing}>{t("common.cancel")}</Button>
<Button type="submit" variant="primary">{t('common.save')}</Button>
<Button onClick={handleCancelEditing}>{t('common.cancel')}</Button>
</div>
)}
</form>
@ -164,7 +169,7 @@ function RoomProfile({ roomId }) {
<IconButton
src={PencilIC}
size="extra-small"
tooltip={t("common.edit")}
tooltip={t('common.edit')}
onClick={() => setIsEditing(true)}
/>
)}

View file

@ -4,6 +4,7 @@ import './RoomSearch.scss';
import dateFormat from 'dateformat';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { selectRoom } from '../../../client/action/navigation';
@ -20,8 +21,7 @@ import SearchIC from '../../../../public/res/ic/outlined/search.svg';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const roomIdToBackup = new Map();
@ -144,37 +144,37 @@ function RoomSearch({ roomId }) {
return (
<div className="room-search">
<form className="room-search__form" onSubmit={handleSearch}>
<MenuHeader>{t("Molecules.RoomSearch.title")}</MenuHeader>
<MenuHeader>{t('Molecules.RoomSearch.title')}</MenuHeader>
<div>
<Input
placeholder={t("Molecules.RoomSearch.placeholder")}
placeholder={t('Molecules.RoomSearch.placeholder')}
name="room-search-input"
disabled={isRoomEncrypted}
autoFocus
/>
<Button iconSrc={SearchIC} variant="primary" type="submit">{t("Molecules.RoomSearch.search_button")}</Button>
<Button iconSrc={SearchIC} variant="primary" type="submit">{t('Molecules.RoomSearch.search_button')}</Button>
</div>
{searchData?.results.length > 0 && (
<Text>{t("Molecules.RoomSearch.results", {count: searchData.count, term: searchTerm})}</Text>
<Text>{t('Molecules.RoomSearch.results', { count: searchData.count, term: searchTerm })}</Text>
)}
{!isRoomEncrypted && searchData === null && (
<div className="room-search__help">
{status.type === cons.status.IN_FLIGHT && <Spinner />}
{status.type === cons.status.IN_FLIGHT && <Text>{t("Molecules.RoomSearch.searching")}</Text>}
{status.type === cons.status.IN_FLIGHT && <Text>{t('Molecules.RoomSearch.searching')}</Text>}
{status.type === cons.status.PRE_FLIGHT && <RawIcon src={SearchIC} size="large" />}
{status.type === cons.status.PRE_FLIGHT && <Text>{t("Molecules.RoomSearch.subtitle")}</Text>}
{status.type === cons.status.ERROR && <Text>{t("Molecules.RoomSearch.failed")}</Text>}
{status.type === cons.status.PRE_FLIGHT && <Text>{t('Molecules.RoomSearch.subtitle')}</Text>}
{status.type === cons.status.ERROR && <Text>{t('Molecules.RoomSearch.failed')}</Text>}
</div>
)}
{!isRoomEncrypted && searchData?.results.length === 0 && (
<div className="room-search__help">
<Text>{t("Molecules.RoomSearch.no_results")}</Text>
<Text>{t('Molecules.RoomSearch.no_results')}</Text>
</div>
)}
{isRoomEncrypted && (
<div className="room-search__help">
<Text>{t("Molecules.RoomSearch.encrypted_room")}</Text>
<Text>{t('Molecules.RoomSearch.encrypted_room')}</Text>
</div>
)}
</form>
@ -189,7 +189,7 @@ function RoomSearch({ roomId }) {
{searchData?.next_batch && (
<div className="room-search__more">
{status.type !== cons.status.IN_FLIGHT && (
<Button onClick={paginate}>{t("Molecules.RoomSearch.load_more")}</Button>
<Button onClick={paginate}>{t('Molecules.RoomSearch.load_more')}</Button>
)}
{status.type === cons.status.IN_FLIGHT && <Spinner />}
</div>

View file

@ -2,18 +2,22 @@ import React from 'react';
import PropTypes from 'prop-types';
import './RoomTile.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import colorMXID from '../../../util/colorMXID';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import { t } from 'i18next';
import '../../i18n';
function RoomTile({
avatarSrc, name, id,
inviterName, memberCount, desc, options,
}) {
const { t } = useTranslation();
return (
<div className="room-tile">
<div className="room-tile__avatar">
@ -28,8 +32,8 @@ function RoomTile({
<Text variant="b3">
{
inviterName !== null
? t("Molecules.RoomTile.invited_by_user", {inviter: inviterName, count: memberCount || 0, id: id})
: t("Molecules.RoomTile.invited", {count: memberCount || 0, id: id})
? t('Molecules.RoomTile.invited_by_user', { inviter: inviterName, count: memberCount || 0, id })
: t('Molecules.RoomTile.invited', { count: memberCount || 0, id })
}
</Text>
{

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import './RoomVisibility.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
@ -15,8 +16,7 @@ import SpaceIC from '../../../../public/res/ic/outlined/space.svg';
import SpaceLockIC from '../../../../public/res/ic/outlined/space-lock.svg';
import SpaceGlobeIC from '../../../../public/res/ic/outlined/space-globe.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const visibility = {
INVITE: 'invite',

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './SpaceAddExisting.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -25,9 +26,7 @@ import SearchIC from '../../../../public/res/ic/outlined/search.svg';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function SpaceAddExistingContent({ roomId }) {
const mountStore = useStore(roomId);
@ -41,7 +40,6 @@ function SpaceAddExistingContent({ roomId }) {
spaces, rooms, directs, roomIdToParents,
} = initMatrix.roomList;
const { t } = useTranslation();
useEffect(() => {
@ -66,7 +64,7 @@ function SpaceAddExistingContent({ roomId }) {
};
const handleAdd = async () => {
setProcess(t("Molecules.SpaceAddExisting.adding_items", {count: selected.length}));
setProcess(t('Molecules.SpaceAddExisting.adding_items', { count: selected.length }));
const promises = selected.map((rId) => {
const room = mx.getRoom(rId);
@ -126,12 +124,12 @@ function SpaceAddExistingContent({ roomId }) {
<Input
name="searchInput"
onChange={handleSearch}
placeholder={t("Molecules.SpaceAddExisting.search_rooms_placeholder")}
placeholder={t('Molecules.SpaceAddExisting.search_rooms_placeholder')}
autoFocus
/>
<IconButton size="small" type="button" onClick={handleSearchClear} src={CrossIC} />
</form>
{searchIds?.length === 0 && <Text>{t("Molecules.SpaceAddExisting.no_results")}</Text>}
{searchIds?.length === 0 && <Text>{t('Molecules.SpaceAddExisting.no_results')}</Text>}
{
(searchIds || allRoomIds).map((rId) => {
const room = mx.getRoom(rId);
@ -178,9 +176,9 @@ function SpaceAddExistingContent({ roomId }) {
{selected.length !== 0 && (
<div className="space-add-existing__footer">
{process && <Spinner size="small" />}
<Text weight="medium">{t("Molecules.SpaceAddExisting.items_selected", {count: selected.length})}</Text>
<Text weight="medium">{t('Molecules.SpaceAddExisting.items_selected', { count: selected.length })}</Text>
{ !process && (
<Button onClick={handleAdd} variant="primary">{t("Molecules.SpaceAddExisting.add_button")}</Button>
<Button onClick={handleAdd} variant="primary">{t('Molecules.SpaceAddExisting.add_button')}</Button>
)}
</div>
)}
@ -212,6 +210,8 @@ function SpaceAddExisting() {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const { t } = useTranslation();
return (
<Dialog
isOpen={roomId !== null}
@ -219,10 +219,15 @@ function SpaceAddExisting() {
title={(
<Text variant="s1" weight="medium" primary>
{roomId && twemojify(room.name)}
<span style={{ color: 'var(--tc-surface-low)' }}> {t("Molecules.SpaceAddExisting.subtitle")}</span>
<span style={{ color: 'var(--tc-surface-low)' }}>
{' '}
{' '}
{t('Molecules.SpaceAddExisting.subtitle')}
</span>
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t('common.close')} />}
onRequestClose={requestClose}
>
{

View file

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -26,8 +27,7 @@ import PinFilledIC from '../../../../public/res/ic/filled/pin.svg';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function SpaceOptions({ roomId, afterOptionSelect }) {
const mx = initMatrix.matrixClient;
@ -64,9 +64,9 @@ function SpaceOptions({ roomId, afterOptionSelect }) {
const handleLeaveClick = async () => {
afterOptionSelect();
const isConfirmed = await confirmDialog(
t("Molecules.SpaceOptions.leave_space"),
t("Molecules.SpaceOptions.leave_space_confirmation", {space: room.name}),
t("Molecules.SpaceOptions.leave_space_confirmation"),
t('Molecules.SpaceOptions.leave_space'),
t('Molecules.SpaceOptions.leave_space_confirmation', { space: room.name }),
t('Molecules.SpaceOptions.leave_space_confirmation'),
'danger',
);
if (!isConfirmed) return;
@ -80,29 +80,29 @@ function SpaceOptions({ roomId, afterOptionSelect }) {
onClick={handleCategorizeClick}
iconSrc={isCategorized ? CategoryFilledIC : CategoryIC}
>
{isCategorized ? t("Organisms.SpaceSettings.uncategorize_subspaces") : t("Organisms.SpaceSettings.categorize_subspaces")}
{isCategorized ? t('Organisms.SpaceSettings.uncategorize_subspaces') : t('Organisms.SpaceSettings.categorize_subspaces')}
</MenuItem>
<MenuItem
onClick={handlePinClick}
iconSrc={isPinned ? PinFilledIC : PinIC}
>
{isPinned ? t("Organisms.SpaceSettings.unpin_sidebar") : t("Organisms.SpaceSettings.pin_sidebar")}
{isPinned ? t('Organisms.SpaceSettings.unpin_sidebar') : t('Organisms.SpaceSettings.pin_sidebar')}
</MenuItem>
<MenuItem
iconSrc={AddUserIC}
onClick={handleInviteClick}
disabled={!canInvite}
>
{t("Molecules.SpaceOptions.invite")}
{t('Molecules.SpaceOptions.invite')}
</MenuItem>
<MenuItem onClick={handleManageRoom} iconSrc={HashSearchIC}>{t("Molecules.SpaceOptions.manage_rooms")}</MenuItem>
<MenuItem onClick={handleSettingsClick} iconSrc={SettingsIC}>{t("Molecules.SpaceOptions.settings")}</MenuItem>
<MenuItem onClick={handleManageRoom} iconSrc={HashSearchIC}>{t('Molecules.SpaceOptions.manage_rooms')}</MenuItem>
<MenuItem onClick={handleSettingsClick} iconSrc={SettingsIC}>{t('Molecules.SpaceOptions.settings')}</MenuItem>
<MenuItem
variant="danger"
onClick={handleLeaveClick}
iconSrc={LeaveArrowIC}
>
{t("Molecules.SpaceOptions.leave")}
{t('Molecules.SpaceOptions.leave')}
</MenuItem>
</div>
);

View file

@ -2,12 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import './SSOButtons.scss';
import { useTranslation } from 'react-i18next';
import { createTemporaryClient, startSsoLogin } from '../../../client/action/auth';
import Button from '../../atoms/button/Button';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function SSOButtons({ type, identityProviders, baseUrl }) {
const tempClient = createTemporaryClient(baseUrl);
@ -28,7 +28,7 @@ function SSOButtons({ type, identityProviders, baseUrl }) {
<button key={idp.id} type="button" className="sso-btn" onClick={() => handleClick(idp.id)}>
<img className="sso-btn__img" src={tempClient.mxcUrlToHttp(idp.icon)} alt={idp.name} />
</button>
) : <Button key={idp.id} className="sso-btn__text-only" onClick={() => handleClick(idp.id)}>{t("Molecules.SSOButtons.login_with", {idp_name: idp.name})}</Button>
) : <Button key={idp.id} className="sso-btn__text-only" onClick={() => handleClick(idp.id)}>{t('Molecules.SSOButtons.login_with', { idp_name: idp.name })}</Button>
))}
</div>
);

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './CreateRoom.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
@ -33,12 +34,9 @@ import SpaceGlobeIC from '../../../../public/res/ic/outlined/space-globe.svg';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
const { t } = useTranslation();
const [joinRule, setJoinRule] = useState(parentId ? 'restricted' : 'invite');
@ -137,8 +135,8 @@ function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
};
const joinRules = ['invite', 'restricted', 'public'];
const joinRuleShortText = [ t("Organisms.CreateRoom.private_room_short"), t("Organisms.CreateRoom.restricted_room_short"), t("Organisms.CreateRoom.public_room_short")];
const joinRuleText = [ t("Organisms.CreateRoom.private_room_long"), t("Organisms.CreateRoom.restricted_room_long"), t("Organisms.CreateRoom.public_room_long")];
const joinRuleShortText = [t('Organisms.CreateRoom.private_room_short'), t('Organisms.CreateRoom.restricted_room_short'), t('Organisms.CreateRoom.public_room_short')];
const joinRuleText = [t('Organisms.CreateRoom.private_room_long'), t('Organisms.CreateRoom.restricted_room_long'), t('Organisms.CreateRoom.public_room_long')];
const jrRoomIC = [HashLockIC, HashIC, HashGlobeIC];
const jrSpaceIC = [SpaceLockIC, SpaceIC, SpaceGlobeIC];
const handleJoinRule = (evt) => {
@ -147,7 +145,7 @@ function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
getEventCords(evt, '.btn-surface'),
(closeMenu) => (
<>
<MenuHeader>{t("Organisms.CreateRoom.visibility_message")}</MenuHeader>
<MenuHeader>{t('Organisms.CreateRoom.visibility_message')}</MenuHeader>
{
joinRules.map((rule) => (
<MenuItem
@ -174,17 +172,17 @@ function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
<div className="create-room">
<form className="create-room__form" onSubmit={handleSubmit}>
<SettingTile
title={t("Organisms.CreateRoom.visibility_title")}
title={t('Organisms.CreateRoom.visibility_title')}
options={(
<Button onClick={handleJoinRule} iconSrc={ChevronBottomIC}>
{joinRuleShortText[joinRules.indexOf(joinRule)]}
</Button>
)}
content={<Text variant="b3">{isSpace ? t("Organisms.CreateRoom.select_who_can_join_space") : t("Organisms.CreateRoom.select_who_can_join_room")}</Text>}
content={<Text variant="b3">{isSpace ? t('Organisms.CreateRoom.select_who_can_join_space') : t('Organisms.CreateRoom.select_who_can_join_room')}</Text>}
/>
{joinRule === 'public' && (
<div>
<Text className="create-room__address__label" variant="b2">{isSpace ? t("Organisms.CreateRoom.space_address") : t("Organisms.CreateRoom.room_address")}</Text>
<Text className="create-room__address__label" variant="b2">{isSpace ? t('Organisms.CreateRoom.space_address') : t('Organisms.CreateRoom.room_address')}</Text>
<div className="create-room__address">
<Text variant="b1">#</Text>
<Input
@ -197,32 +195,40 @@ function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
/>
<Text variant="b1">{`:${userHs}`}</Text>
</div>
{isValidAddress === false && <Text className="create-room__address__tip" variant="b3"><span style={{ color: 'var(--bg-danger)' }}>{ t("Organisms.CreateRoom.room_address_already_in_use", {room_address: `#${addressValue}:${userHs}`})}</span></Text>}
{isValidAddress === false && <Text className="create-room__address__tip" variant="b3"><span style={{ color: 'var(--bg-danger)' }}>{ t('Organisms.CreateRoom.room_address_already_in_use', { room_address: `#${addressValue}:${userHs}` })}</span></Text>}
</div>
)}
{!isSpace && joinRule !== 'public' && (
<SettingTile
title={t("Organisms.CreateRoom.e2e_title")}
title={t('Organisms.CreateRoom.e2e_title')}
options={<Toggle isActive={isEncrypted} onToggle={setIsEncrypted} />}
content={<Text variant="b3"> {t("Organisms.CreateRoom.e2e_message")}</Text>}
content={(
<Text variant="b3">
{' '}
{t('Organisms.CreateRoom.e2e_message')}
</Text>
)}
/>
)}
<SettingTile
title={t("Organisms.CreateRoom.role_title")}
title={t('Organisms.CreateRoom.role_title')}
options={(
<SegmentControl
selected={roleIndex}
segments={[{ text: t("Organisms.CreateRoom.role_admin")}, { text: t("Organisms.CreateRoom.role_founder")}]}
segments={[{ text: t('Organisms.CreateRoom.role_admin') }, { text: t('Organisms.CreateRoom.role_founder') }]}
onSelect={setRoleIndex}
/>
)}
content={(
<Text variant="b3"> {t("Organisms.CreateRoom.role_message")}</Text>
<Text variant="b3">
{' '}
{t('Organisms.CreateRoom.role_message')}
</Text>
)}
/>
<Input name="topic" minHeight={174} resizable label= {t("Organisms.CreateRoom.topic_label")}/>
<Input name="topic" minHeight={174} resizable label={t('Organisms.CreateRoom.topic_label')} />
<div className="create-room__name-wrapper">
<Input name="name" label={isSpace ? t("Organisms.CreateRoom.space_name"): t("Organisms.CreateRoom.room_name")} required />
<Input name="name" label={isSpace ? t('Organisms.CreateRoom.space_name') : t('Organisms.CreateRoom.room_name')} required />
<Button
disabled={isValidAddress === false || isCreatingRoom}
iconSrc={isSpace ? SpacePlusIC : HashPlusIC}
@ -235,7 +241,7 @@ function CreateRoomContent({ isSpace, parentId, onRequestClose }) {
{isCreatingRoom && (
<div className="create-room__loading">
<Spinner size="small" />
<Text>{ isSpace ? t("Organisms.CreateRoom.creating_space") : t("Organisms.CreateRoom.creating_room")}</Text>
<Text>{ isSpace ? t('Organisms.CreateRoom.creating_space') : t('Organisms.CreateRoom.creating_room')}</Text>
</div>
)}
{typeof creatingError === 'string' && <Text className="create-room__error" variant="b3">{creatingError}</Text>}
@ -279,18 +285,20 @@ function CreateRoom() {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(parentId);
const { t } = useTranslation();
return (
<Dialog
isOpen={create !== null}
title={(
<Text variant="s1" weight="medium" primary>
{parentId ? twemojify(room.name) : t("Organisms.CreateRoom.home")}
{parentId ? twemojify(room.name) : t('Organisms.CreateRoom.home')}
<span style={{ color: 'var(--tc-surface-low)' }}>
{`${isSpace ? t("Organisms.CreateRoom.create_space") : t("Organisms.CreateRoom.create_room")}`}
{`${isSpace ? t('Organisms.CreateRoom.create_space') : t('Organisms.CreateRoom.create_room')}`}
</span>
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t('common.close')} />}
onRequestClose={onRequestClose}
>
{

View file

@ -2,14 +2,14 @@ import React from 'react';
import PropTypes from 'prop-types';
import './DragDrop.scss';
import { useTranslation } from 'react-i18next';
import RawModal from '../../atoms/modal/RawModal';
import Text from '../../atoms/text/Text';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function DragDrop({ isOpen }) {
const { t } = useTranslation();
return (
@ -18,7 +18,7 @@ function DragDrop({ isOpen }) {
overlayClassName="drag-drop__overlay"
isOpen={isOpen}
>
<Text variant="h2" weight="medium">{t("Organisms.DragDrop.drop_file_to_upload_prompt")}</Text>
<Text variant="h2" weight="medium">{t('Organisms.DragDrop.drop_file_to_upload_prompt')}</Text>
</RawModal>
);
}

View file

@ -2,6 +2,7 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './EmojiVerification.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -20,9 +21,7 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useStore } from '../../hooks/useStore';
import { accessSecretStorage } from '../settings/SecretStorageAccess';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function EmojiVerificationContent({ data, requestClose }) {
const [sas, setSas] = useState(null);
@ -100,14 +99,14 @@ function EmojiVerificationContent({ data, requestClose }) {
const renderWait = () => (
<>
<Spinner size="small" />
<Text>{t("Organisms.EmojiVerification.waiting_for_response")}</Text>
<Text>{t('Organisms.EmojiVerification.waiting_for_response')}</Text>
</>
);
if (sas !== null) {
return (
<div className="emoji-verification__content">
<Text>{t("Organisms.EmojiVerification.confirmation_prompt")}</Text>
<Text>{t('Organisms.EmojiVerification.confirmation_prompt')}</Text>
<div className="emoji-verification__emojis">
{sas.sas.emoji.map((emoji, i) => (
// eslint-disable-next-line react/no-array-index-key
@ -120,8 +119,8 @@ function EmojiVerificationContent({ data, requestClose }) {
<div className="emoji-verification__buttons">
{process ? renderWait() : (
<>
<Button variant="primary" onClick={sasConfirm}>{t("Organisms.EmojiVerification.emojis_match_button")}</Button>
<Button onClick={sasMismatch}>{t("Organisms.EmojiVerification.emojis_dont_match_button")}</Button>
<Button variant="primary" onClick={sasConfirm}>{t('Organisms.EmojiVerification.emojis_match_button')}</Button>
<Button onClick={sasMismatch}>{t('Organisms.EmojiVerification.emojis_dont_match_button')}</Button>
</>
)}
</div>
@ -132,7 +131,7 @@ function EmojiVerificationContent({ data, requestClose }) {
if (targetDevice) {
return (
<div className="emoji-verification__content">
<Text>{t("Organisms.EmojiVerification.accept_request_from_other_device_message")}</Text>
<Text>{t('Organisms.EmojiVerification.accept_request_from_other_device_message')}</Text>
<div className="emoji-verification__buttons">
{renderWait()}
</div>
@ -142,12 +141,12 @@ function EmojiVerificationContent({ data, requestClose }) {
return (
<div className="emoji-verification__content">
<Text>{t("Organisms.EmojiVerification.begin_verification_process_message")}</Text>
<Text>{t('Organisms.EmojiVerification.begin_verification_process_message')}</Text>
<div className="emoji-verification__buttons">
{
process
? renderWait()
: <Button variant="primary" onClick={beginVerification}>{t("Organisms.EmojiVerification.begin_verification_button_text")}</Button>
: <Button variant="primary" onClick={beginVerification}>{t('Organisms.EmojiVerification.begin_verification_button_text')}</Button>
}
</div>
</div>
@ -182,16 +181,18 @@ function useVisibilityToggle() {
function EmojiVerification() {
const [data, requestClose] = useVisibilityToggle();
const { t } = useTranslation();
return (
<Dialog
isOpen={data !== null}
className="emoji-verification"
title={(
<Text variant="s1" weight="medium" primary>
{t("Organisms.EmojiVerification.title")}
{t('Organisms.EmojiVerification.title')}
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t('common.close')} />}
onRequestClose={requestClose}
>
{

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './InviteList.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import * as roomActions from '../../../client/action/room';
@ -16,11 +17,7 @@ import RoomTile from '../../molecules/room-tile/RoomTile';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function InviteList({ isOpen, onRequestClose }) {
const [procInvite, changeProcInvite] = useState(new Set());
@ -81,8 +78,8 @@ function InviteList({ isOpen, onRequestClose }) {
? (<Spinner size="small" />)
: (
<div className="invite-btn__container">
<Button onClick={() => rejectInvite(myRoom.roomId)}>{t("Organisms.InviteList.reject_invite")}</Button>
<Button onClick={() => acceptInvite(myRoom.roomId)} variant="primary">{t("Organisms.InviteList.accept_invite")}</Button>
<Button onClick={() => rejectInvite(myRoom.roomId)}>{t('Organisms.InviteList.reject_invite')}</Button>
<Button onClick={() => acceptInvite(myRoom.roomId)} variant="primary">{t('Organisms.InviteList.accept_invite')}</Button>
</div>
)
}
@ -93,14 +90,14 @@ function InviteList({ isOpen, onRequestClose }) {
return (
<PopupWindow
isOpen={isOpen}
title={t("Organisms.InviteList.title")}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t("common.close")} />}
title={t('Organisms.InviteList.title')}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t('common.close')} />}
onRequestClose={onRequestClose}
>
<div className="invites-content">
{ initMatrix.roomList.inviteDirects.size !== 0 && (
<div className="invites-content__subheading">
<Text variant="b3" weight="bold">{t("Organisms.InviteList.direct_messages_title")}</Text>
<Text variant="b3" weight="bold">{t('Organisms.InviteList.direct_messages_title')}</Text>
</div>
)}
{
@ -118,8 +115,8 @@ function InviteList({ isOpen, onRequestClose }) {
? (<Spinner size="small" />)
: (
<div className="invite-btn__container">
<Button onClick={() => rejectInvite(myRoom.roomId, true)}>{t("Organisms.InviteList.reject_invite")}</Button>
<Button onClick={() => acceptInvite(myRoom.roomId, true)} variant="primary">{t("Organisms.InviteList.accept_invite")}</Button>
<Button onClick={() => rejectInvite(myRoom.roomId, true)}>{t('Organisms.InviteList.reject_invite')}</Button>
<Button onClick={() => acceptInvite(myRoom.roomId, true)} variant="primary">{t('Organisms.InviteList.accept_invite')}</Button>
</div>
)
}
@ -129,14 +126,14 @@ function InviteList({ isOpen, onRequestClose }) {
}
{ initMatrix.roomList.inviteSpaces.size !== 0 && (
<div className="invites-content__subheading">
<Text variant="b3" weight="bold">{t("Organisms.InviteList.spaces_title")}</Text>
<Text variant="b3" weight="bold">{t('Organisms.InviteList.spaces_title')}</Text>
</div>
)}
{ Array.from(initMatrix.roomList.inviteSpaces).map(renderRoomTile) }
{ initMatrix.roomList.inviteRooms.size !== 0 && (
<div className="invites-content__subheading">
<Text variant="b3" weight="bold">{t("Organisms.InviteList.rooms_title")}</Text>
<Text variant="b3" weight="bold">{t('Organisms.InviteList.rooms_title')}</Text>
</div>
)}
{ Array.from(initMatrix.roomList.inviteRooms).map(renderRoomTile) }

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './InviteUser.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import * as roomActions from '../../../client/action/room';
@ -19,9 +20,7 @@ import RoomTile from '../../molecules/room-tile/RoomTile';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import UserIC from '../../../../public/res/ic/outlined/user.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function InviteUser({
isOpen, roomId, searchTerm, onRequestClose,
@ -88,7 +87,7 @@ function InviteUser({
avatar_url: result.avatar_url,
}]);
} catch (e) {
updateSearchQuery({error: t("Organisms.InviteUser.user_not_found", {user_name: inputUsername})});
updateSearchQuery({ error: t('Organisms.InviteUser.user_not_found', { user_name: inputUsername }) });
}
} else {
try {
@ -97,13 +96,13 @@ function InviteUser({
limit: 20,
});
if (result.results.length === 0) {
updateSearchQuery({ error: t("Organisms.InviteUser.no_matches_found", {user_name: inputUsername})});
updateSearchQuery({ error: t('Organisms.InviteUser.no_matches_found', { user_name: inputUsername }) });
updateIsSearching(false);
return;
}
updateUsers(result.results);
} catch (e) {
updateSearchQuery({ error: t("errors.generic")});
updateSearchQuery({ error: t('errors.generic') });
}
}
updateIsSearching(false);
@ -112,9 +111,7 @@ function InviteUser({
async function hasDevices(userId) {
try {
const usersDeviceMap = await mx.downloadKeys([userId, mx.getUserId()]);
return Object.values(usersDeviceMap).every((userDevices) =>
Object.keys(userDevices).length > 0,
);
return Object.values(usersDeviceMap).every((userDevices) => Object.keys(userDevices).length > 0);
} catch (e) {
console.error("Error determining if it's possible to encrypt to all users: ", e);
return false;
@ -141,7 +138,7 @@ function InviteUser({
} catch (e) {
deleteUserFromProc(userId);
if (typeof e.message === 'string') procUserError.set(userId, e.message);
else procUserError.set(userId, t("errors.generic"));
else procUserError.set(userId, t('errors.generic'));
updateUserProcError(getMapCopy(procUserError));
}
}
@ -161,7 +158,7 @@ function InviteUser({
} catch (e) {
deleteUserFromProc(userId);
if (typeof e.message === 'string') procUserError.set(userId, e.message);
else procUserError.set(userId, t("errors.generic"));
else procUserError.set(userId, t('errors.generic'));
updateUserProcError(getMapCopy(procUserError));
}
}
@ -179,7 +176,7 @@ function InviteUser({
return <Button onClick={() => { selectRoom(createdDM.get(userId)); onRequestClose(); }}>Open</Button>;
}
if (invitedUserIds.has(userId)) {
return messageJSX(t("Organisms.InviteUser.invite_result.invited"), true);
return messageJSX(t('Organisms.InviteUser.invite_result.invited'), true);
}
if (typeof roomId === 'string') {
const member = mx.getRoom(roomId).getMember(userId);
@ -187,18 +184,18 @@ function InviteUser({
const userMembership = member.membership;
switch (userMembership) {
case 'join':
return messageJSX(t("Organisms.InviteUser.invite_result.already_joined"), true);
return messageJSX(t('Organisms.InviteUser.invite_result.already_joined'), true);
case 'invite':
return messageJSX(t("Organisms.InviteUser.invite_result.already_invited"), true);
return messageJSX(t('Organisms.InviteUser.invite_result.already_invited'), true);
case 'ban':
return messageJSX(t("Organisms.InviteUser.invite_result.banned"), false);
return messageJSX(t('Organisms.InviteUser.invite_result.banned'), false);
default:
}
}
}
return (typeof roomId === 'string')
? <Button onClick={() => inviteToRoom(userId)} variant="primary">{t("common.invite")}</Button>
: <Button onClick={() => createDM(userId)} variant="primary">{t("common.message_prompt")}</Button>;
? <Button onClick={() => inviteToRoom(userId)} variant="primary">{t('common.invite')}</Button>
: <Button onClick={() => createDM(userId)} variant="primary">{t('common.message_prompt')}</Button>;
};
const renderError = (userId) => {
if (!procUserError.has(userId)) return null;
@ -245,27 +242,27 @@ function InviteUser({
return (
<PopupWindow
isOpen={isOpen}
title={(typeof roomId === 'string' ? t("Organisms.InviteUser.invite_to_room", {room: mx.getRoom(roomId).name}) : t("Organisms.InviteUser.invite_to_dm"))}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t("common.close")} />}
title={(typeof roomId === 'string' ? t('Organisms.InviteUser.invite_to_room', { room: mx.getRoom(roomId).name }) : t('Organisms.InviteUser.invite_to_dm'))}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t('common.close')} />}
onRequestClose={onRequestClose}
>
<div className="invite-user">
<form className="invite-user__form" onSubmit={(e) => { e.preventDefault(); searchUser(usernameRef.current.value); }}>
<Input value={searchTerm} forwardRef={usernameRef} label={t("Organisms.InviteUser.search_label")} />
<Button disabled={isSearching} iconSrc={UserIC} variant="primary" type="submit">{t("common.search")}</Button>
<Input value={searchTerm} forwardRef={usernameRef} label={t('Organisms.InviteUser.search_label')} />
<Button disabled={isSearching} iconSrc={UserIC} variant="primary" type="submit">{t('common.search')}</Button>
</form>
<div className="invite-user__search-status">
{
typeof searchQuery.username !== 'undefined' && isSearching && (
<div className="flex--center">
<Spinner size="small" />
<Text variant="b2">{t("Organisms.InviteUser.searching_for_user", {user_name: searchQuery.username})}</Text>
<Text variant="b2">{t('Organisms.InviteUser.searching_for_user', { user_name: searchQuery.username })}</Text>
</div>
)
}
{
typeof searchQuery.username !== 'undefined' && !isSearching && (
<Text variant="b2">{t("Organisms.InviteUser.search_result_title", {user_name: searchQuery.username})}</Text>
<Text variant="b2">{t('Organisms.InviteUser.search_result_title', { user_name: searchQuery.username })}</Text>
)
}
{

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './JoinAlias.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
@ -19,10 +20,7 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
const ALIAS_OR_ID_REG = /^[#|!].+:.+\..+$/;
@ -61,10 +59,10 @@ function JoinAliasContent({ term, requestClose }) {
const alias = e.target.alias.value;
if (alias?.trim() === '') return;
if (alias.match(ALIAS_OR_ID_REG) === null) {
setError(t("Organisms.JoinAlias.invalid_address"));
setError(t('Organisms.JoinAlias.invalid_address'));
return;
}
setProcess(t("Organisms.JoinAlias.looking_for_address"));
setProcess(t('Organisms.JoinAlias.looking_for_address'));
setError(undefined);
let via;
if (alias.startsWith('#')) {
@ -72,12 +70,12 @@ function JoinAliasContent({ term, requestClose }) {
const aliasData = await mx.resolveRoomAlias(alias);
via = aliasData?.servers.slice(0, 3) || [];
if (mountStore.getItem()) {
setProcess(t("Organisms.JoinAlias.joining_alias", {alias_name: alias}));
setProcess(t('Organisms.JoinAlias.joining_alias', { alias_name: alias }));
}
} catch (err) {
if (!mountStore.getItem()) return;
setProcess(false);
setError(t("Organisms.JoinAlias.couldnt_find_room_or_space_alias", {alias_name: alias}));
setError(t('Organisms.JoinAlias.couldnt_find_room_or_space_alias', { alias_name: alias }));
}
}
try {
@ -88,14 +86,14 @@ function JoinAliasContent({ term, requestClose }) {
} catch {
if (!mountStore.getItem()) return;
setProcess(false);
setError(t("Organisms.JoinAlias.couldnt_find_room_or_space", {alias_name: alias}));
setError(t('Organisms.JoinAlias.couldnt_find_room_or_space', { alias_name: alias }));
}
};
return (
<form className="join-alias" onSubmit={handleSubmit}>
<Input
label={t("Organisms.JoinAlias.address_label")}
label={t('Organisms.JoinAlias.address_label')}
value={term}
name="alias"
required
@ -110,7 +108,7 @@ function JoinAliasContent({ term, requestClose }) {
<Text>{process}</Text>
</>
)
: <Button variant="primary" type="submit">{t("common.join")}</Button>
: <Button variant="primary" type="submit">{t('common.join')}</Button>
}
</div>
</form>
@ -145,13 +143,15 @@ function useWindowToggle() {
function JoinAlias() {
const [data, requestClose] = useWindowToggle();
const { t } = useTranslation();
return (
<Dialog
isOpen={data !== null}
title={(
<Text variant="s1" weight="medium" primary>{t("Organisms.JoinAlias.title")}</Text>
<Text variant="s1" weight="medium" primary>{t('Organisms.JoinAlias.title')}</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={"common.close"} />}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip="common.close" />}
onRequestClose={requestClose}
>
{ data ? <JoinAliasContent term={data.term} requestClose={requestClose} /> : <div /> }

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './DrawerBreadcrumb.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -18,10 +19,7 @@ import NotificationBadge from '../../atoms/badge/NotificationBadge';
import ChevronRightIC from '../../../../public/res/ic/outlined/chevron-right.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function DrawerBreadcrumb({ spaceId }) {
const [, forceUpdate] = useState({});
@ -116,7 +114,7 @@ function DrawerBreadcrumb({ spaceId }) {
className={index === spacePath.length - 1 ? 'drawer-breadcrumb__btn--selected' : ''}
onClick={() => selectSpace(id)}
>
<Text variant="b2">{id === cons.tabs.HOME ? t("Organisms.DrawerBreadcrumb.home") : twemojify(mx.getRoom(id).name)}</Text>
<Text variant="b2">{id === cons.tabs.HOME ? t('Organisms.DrawerBreadcrumb.home') : twemojify(mx.getRoom(id).name)}</Text>
{ noti !== null && (
<NotificationBadge
alert={noti.highlight !== 0}

View file

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import './DrawerHeader.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -28,10 +29,7 @@ import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg';
import SpacePlusIC from '../../../../public/res/ic/outlined/space-plus.svg';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
const mx = initMatrix.matrixClient;
@ -44,27 +42,27 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
return (
<>
<MenuHeader>{t("Organisms.DrawerHeader.add_rooms_or_spaces")}</MenuHeader>
<MenuHeader>{t('Organisms.DrawerHeader.add_rooms_or_spaces')}</MenuHeader>
<MenuItem
iconSrc={SpacePlusIC}
onClick={() => { afterOptionSelect(); openCreateRoom(true, spaceId); }}
disabled={!canManage}
>
{t("Organisms.DrawerHeader.create_new_space")}
{t('Organisms.DrawerHeader.create_new_space')}
</MenuItem>
<MenuItem
iconSrc={HashPlusIC}
onClick={() => { afterOptionSelect(); openCreateRoom(false, spaceId); }}
disabled={!canManage}
>
{t("Organisms.DrawerHeader.create_new_room")}
{t('Organisms.DrawerHeader.create_new_room')}
</MenuItem>
{ !spaceId && (
<MenuItem
iconSrc={HashGlobeIC}
onClick={() => { afterOptionSelect(); openPublicRooms(); }}
>
{t("Organisms.DrawerHeader.join_public_room")}
{t('Organisms.DrawerHeader.join_public_room')}
</MenuItem>
)}
{ !spaceId && (
@ -72,7 +70,7 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
iconSrc={PlusIC}
onClick={() => { afterOptionSelect(); openJoinAlias(); }}
>
{t("Organisms.DrawerHeader.join_with_address")}
{t('Organisms.DrawerHeader.join_with_address')}
</MenuItem>
)}
{ spaceId && (
@ -81,7 +79,7 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
onClick={() => { afterOptionSelect(); openSpaceAddExisting(spaceId); }}
disabled={!canManage}
>
{t("Organisms.DrawerHeader.add_existing")}
{t('Organisms.DrawerHeader.add_existing')}
</MenuItem>
)}
{ spaceId && (
@ -89,7 +87,7 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
onClick={() => { afterOptionSelect(); openSpaceManage(spaceId); }}
iconSrc={HashSearchIC}
>
{t("Organisms.DrawerHeader.manage_rooms")}
{t('Organisms.DrawerHeader.manage_rooms')}
</MenuItem>
)}
</>
@ -105,7 +103,8 @@ HomeSpaceOptions.propTypes = {
function DrawerHeader({ selectedTab, spaceId }) {
const mx = initMatrix.matrixClient;
const tabName = selectedTab !== cons.tabs.DIRECTS ? t("Organisms.DrawerHeader.home") : t("Organisms.DrawerHeader.direct_messages");
const { t } = useTranslation();
const tabName = selectedTab !== cons.tabs.DIRECTS ? t('Organisms.DrawerHeader.home') : t('Organisms.DrawerHeader.direct_messages');
const isDMTab = selectedTab === cons.tabs.DIRECTS;
const room = mx.getRoom(spaceId);
@ -149,8 +148,8 @@ function DrawerHeader({ selectedTab, spaceId }) {
</TitleWrapper>
)}
{ isDMTab && <IconButton onClick={() => openInviteUser()} tooltip={t("Organisms.DrawerHeader.start_dm_tooltip")} src={PlusIC} size="small" /> }
{ !isDMTab && <IconButton onClick={openHomeSpaceOptions} tooltip={t("Organisms.DrawerHeader.add_rooms_spaces_tooltip")} src={PlusIC} size="small" /> }
{ isDMTab && <IconButton onClick={() => openInviteUser()} tooltip={t('Organisms.DrawerHeader.start_dm_tooltip')} src={PlusIC} size="small" /> }
{ !isDMTab && <IconButton onClick={openHomeSpaceOptions} tooltip={t('Organisms.DrawerHeader.add_rooms_spaces_tooltip')} src={PlusIC} size="small" /> }
</Header>
);
}

View file

@ -2,6 +2,7 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
@ -18,8 +19,7 @@ import VerticalMenuIC from '../../../../public/res/ic/outlined/vertical-menu.svg
import { useForceUpdate } from '../../hooks/useForceUpdate';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function Selector({
roomId, isDM, drawerPostie, onClick,
@ -74,7 +74,7 @@ function Selector({
options={(
<IconButton
size="extra-small"
tooltip={t("common.options")}
tooltip={t('common.options')}
tooltipPlacement="right"
src={VerticalMenuIC}
onClick={openOptions}

View file

@ -5,6 +5,7 @@ import './SideBar.scss';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import colorMXID from '../../../util/colorMXID';
@ -34,10 +35,7 @@ import { useDeviceList } from '../../hooks/useDeviceList';
import { tabText as settingTabText } from '../settings/Settings';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function useNotificationUpdate() {
const { notifications } = initMatrix;
@ -55,7 +53,6 @@ function useNotificationUpdate() {
}
function ProfileAvatarMenu() {
const { t } = useTranslation();
const mx = initMatrix.matrixClient;
@ -85,7 +82,7 @@ function ProfileAvatarMenu() {
return (
<SidebarAvatar
onClick={openSettings}
tooltip={t("Organisms.SideBar.settings_tooltip")}
tooltip={t('Organisms.SideBar.settings_tooltip')}
avatar={(
<Avatar
text={profile.displayName}
@ -99,6 +96,7 @@ function ProfileAvatarMenu() {
}
function CrossSigninAlert() {
const { t } = useTranslation();
const deviceList = useDeviceList();
const unverified = deviceList?.filter((device) => isCrossVerified(device.device_id) === false);
@ -107,7 +105,7 @@ function CrossSigninAlert() {
return (
<SidebarAvatar
className="sidebar__cross-signin-alert"
tooltip={t("Organisms.SideBar.unverified_sessions", {count: unverified.length})}
tooltip={t('Organisms.SideBar.unverified_sessions', { count: unverified.length })}
onClick={() => openSettings(settingTabText.SECURITY)}
avatar={<Avatar iconSrc={ShieldUserIC} iconColor="var(--ic-danger-normal)" size="normal" />}
/>
@ -117,6 +115,7 @@ function CrossSigninAlert() {
function FeaturedTab() {
const { roomList, accountData, notifications } = initMatrix;
const [selectedTab] = useSelectedTab();
const { t } = useTranslation();
useNotificationUpdate();
function getHomeNoti() {
@ -155,7 +154,7 @@ function FeaturedTab() {
return (
<>
<SidebarAvatar
tooltip={t("Organisms.SideBar.home_tooltip")}
tooltip={t('Organisms.SideBar.home_tooltip')}
active={selectedTab === cons.tabs.HOME}
onClick={() => selectTab(cons.tabs.HOME)}
avatar={<Avatar iconSrc={HomeIC} size="normal" />}
@ -167,7 +166,7 @@ function FeaturedTab() {
) : null}
/>
<SidebarAvatar
tooltip={t("Organisms.SideBar.direct_messages_tooltip")}
tooltip={t('Organisms.SideBar.direct_messages_tooltip')}
active={selectedTab === cons.tabs.DIRECTS}
onClick={() => selectTab(cons.tabs.DIRECTS)}
avatar={<Avatar iconSrc={UserIC} size="normal" />}
@ -350,6 +349,7 @@ function useTotalInvites() {
function SideBar() {
const [totalInvites] = useTotalInvites();
const { t } = useTranslation();
return (
<div className="sidebar">
@ -363,7 +363,7 @@ function SideBar() {
<div className="space-container">
<SpaceShortcut />
<SidebarAvatar
tooltip={t("Organisms.SideBar.pin_spaces_tooltip")}
tooltip={t('Organisms.SideBar.pin_spaces_tooltip')}
onClick={() => openShortcutSpaces()}
avatar={<Avatar iconSrc={AddPinIC} size="normal" />}
/>
@ -375,13 +375,13 @@ function SideBar() {
<div className="sidebar-divider" />
<div className="sticky-container">
<SidebarAvatar
tooltip={t("Organisms.SideBar.search_tooltip")}
tooltip={t('Organisms.SideBar.search_tooltip')}
onClick={() => openSearch()}
avatar={<Avatar iconSrc={SearchIC} size="normal" />}
/>
{ totalInvites !== 0 && (
<SidebarAvatar
tooltip={t("Organisms.SideBar.invites_tooltip")}
tooltip={t('Organisms.SideBar.invites_tooltip')}
onClick={() => openInviteList()}
avatar={<Avatar iconSrc={InviteIC} size="normal" />}
notificationBadge={<NotificationBadge alert content={totalInvites} />}

View file

@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -16,10 +17,7 @@ import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog';
import './ProfileEditor.scss';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
// TODO Fix bug that prevents 'Save' button from enabling up until second changed.
function ProfileEditor({ userId }) {
@ -49,9 +47,9 @@ function ProfileEditor({ userId }) {
const handleAvatarUpload = async (url) => {
if (url === null) {
const isConfirmed = await confirmDialog(
t("Organisms.ProfileEditor.remove_avatar"),
t("Organisms.ProfileViewer.remove_avatar_confirmation"),
t("common.remove"),
t('Organisms.ProfileEditor.remove_avatar'),
t('Organisms.ProfileViewer.remove_avatar_confirmation'),
t('common.remove'),
'caution',
);
if (isConfirmed) {
@ -90,13 +88,13 @@ function ProfileEditor({ userId }) {
onSubmit={(e) => { e.preventDefault(); saveDisplayName(); }}
>
<Input
label={t("Organisms.ProfileEditor.display_name_message", {user_name: mx.getUserId()})}
label={t('Organisms.ProfileEditor.display_name_message', { user_name: mx.getUserId() })}
onChange={onDisplayNameInputChange}
value={mx.getUser(mx.getUserId()).displayName}
forwardRef={displayNameRef}
/>
<Button variant="primary" type="submit" disabled={disabled}>{t("common.save")}</Button>
<Button onClick={cancelDisplayNameChanges}>{t("common.cancel")}</Button>
<Button variant="primary" type="submit" disabled={disabled}>{t('common.save')}</Button>
<Button onClick={cancelDisplayNameChanges}>{t('common.cancel')}</Button>
</form>
);
@ -107,7 +105,7 @@ function ProfileEditor({ userId }) {
<IconButton
src={PencilIC}
size="extra-small"
tooltip={t("common.edit")}
tooltip={t('common.edit')}
onClick={() => setIsEditing(true)}
/>
</div>

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './ProfileViewer.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -11,7 +12,7 @@ import { selectRoom, openReusableContextMenu } from '../../../client/action/navi
import * as roomActions from '../../../client/action/room';
import {
getUsername, getUsernameOfRoomMember, getPowerLabel, hasDMWith
getUsername, getUsernameOfRoomMember, getPowerLabel, hasDMWith,
} from '../../../util/matrixUtil';
import { getEventCords } from '../../../util/common';
import colorMXID from '../../../util/colorMXID';
@ -34,14 +35,11 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
function ModerationTools({
roomId, userId,
}) {
const { t } = useTranslation();
const mx = initMatrix.matrixClient;
@ -77,14 +75,14 @@ function ModerationTools({
<div className="moderation-tools">
{canIKick && (
<form onSubmit={handleKick}>
<Input label={t("Organisms.ProfileViewer.kick_reason_label")} name="kick-reason" />
<Button type="submit">{t("Organisms.ProfileViewer.kick_button")}</Button>
<Input label={t('Organisms.ProfileViewer.kick_reason_label')} name="kick-reason" />
<Button type="submit">{t('Organisms.ProfileViewer.kick_button')}</Button>
</form>
)}
{canIBan && (
<form onSubmit={handleBan}>
<Input label={t("Organisms.ProfileViewer.ban_reason_label")} name="ban-reason" />
<Button type="submit">{t("Organisms.ProfileViewer.ban_button")}</Button>
<Input label={t('Organisms.ProfileViewer.ban_reason_label')} name="ban-reason" />
<Button type="submit">{t('Organisms.ProfileViewer.ban_button')}</Button>
</form>
)}
</div>
@ -127,8 +125,8 @@ function SessionInfo({ userId }) {
if (!isVisible) return null;
return (
<div className="session-info__chips">
{devices === null && <Text variant="b2">{t("Organisms.ProfileViewer.loading_sessions")}</Text>}
{devices?.length === 0 && <Text variant="b2">{t("Organisms.ProfileViewer.no_sessions_found")}</Text>}
{devices === null && <Text variant="b2">{t('Organisms.ProfileViewer.loading_sessions')}</Text>}
{devices?.length === 0 && <Text variant="b2">{t('Organisms.ProfileViewer.no_sessions_found')}</Text>}
{devices !== null && (devices.map((device) => (
<Chip
key={device.deviceId}
@ -146,7 +144,7 @@ function SessionInfo({ userId }) {
onClick={() => setIsVisible(!isVisible)}
iconSrc={isVisible ? ChevronBottomIC : ChevronRightIC}
>
<Text variant="b2">{t("Organisms.ProfileViewer.view_sessions", {count: devices?.length})}</Text>
<Text variant="b2">{t('Organisms.ProfileViewer.view_sessions', { count: devices?.length })}</Text>
</MenuItem>
{renderSessionChips()}
</div>
@ -161,6 +159,7 @@ function ProfileFooter({ roomId, userId, onRequestClose }) {
const [isCreatingDM, setIsCreatingDM] = useState(false);
const [isIgnoring, setIsIgnoring] = useState(false);
const [isUserIgnored, setIsUserIgnored] = useState(initMatrix.matrixClient.isUserIgnored(userId));
const { t } = useTranslation();
const isMountedRef = useRef(true);
const mx = initMatrix.matrixClient;
@ -261,7 +260,7 @@ function ProfileFooter({ roomId, userId, onRequestClose }) {
onClick={openDM}
disabled={isCreatingDM}
>
{isCreatingDM ? t("Organisms.ProfileViewer.creating_dm_room") : t("Organisms.ProfileViewer.send_direct_message_button")}
{isCreatingDM ? t('Organisms.ProfileViewer.creating_dm_room') : t('Organisms.ProfileViewer.send_direct_message_button')}
</Button>
{ isBanned && canIKick && (
<Button
@ -278,8 +277,8 @@ function ProfileFooter({ roomId, userId, onRequestClose }) {
>
{
isInvited
? `${isInviting ? t("common.uninviting") : t("common.uninvite")}`
: `${isInviting ? t("common.inviting") : t("common.invite")}`
? `${isInviting ? t('common.uninviting') : t('common.uninvite')}`
: `${isInviting ? t('common.inviting') : t('common.invite')}`
}
</Button>
)}
@ -290,8 +289,8 @@ function ProfileFooter({ roomId, userId, onRequestClose }) {
>
{
isUserIgnored
? `${isIgnoring ? t("Organisms.ProfileViewer.unignoring") : t("Organisms.ProfileViewer.unignore")}`
: `${isIgnoring ? t("Organisms.ProfileViewer.ignoring") : t("Organisms.ProfileViewer.ignore")}`
? `${isIgnoring ? t('Organisms.ProfileViewer.unignoring') : t('Organisms.ProfileViewer.unignore')}`
: `${isIgnoring ? t('Organisms.ProfileViewer.ignoring') : t('Organisms.ProfileViewer.ignore')}`
}
</Button>
</div>
@ -355,6 +354,7 @@ function ProfileViewer() {
const [isOpen, roomId, userId, closeDialog, handleAfterClose] = useToggleDialog();
useRerenderOnProfileChange(roomId, userId);
const { t } = useTranslation();
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
@ -374,16 +374,16 @@ function ProfileViewer() {
const handleChangePowerLevel = async (newPowerLevel) => {
if (newPowerLevel === powerLevel) return;
const SHARED_POWER_MSG = t("Organisms.ProfileViewer.shared_power_message");
const DEMOTING_MYSELF_MSG = t("Organisms.ProfileViewer.demoting_self_message");
const SHARED_POWER_MSG = t('Organisms.ProfileViewer.shared_power_message');
const DEMOTING_MYSELF_MSG = t('Organisms.ProfileViewer.demoting_self_message');
const isSharedPower = newPowerLevel === myPowerLevel;
const isDemotingMyself = userId === mx.getUserId();
if (isSharedPower || isDemotingMyself) {
const isConfirmed = await confirmDialog(
t("Organisms.ProfileViewer.change_power_level"),
t('Organisms.ProfileViewer.change_power_level'),
isSharedPower ? SHARED_POWER_MSG : DEMOTING_MYSELF_MSG,
t("common.change"),
t('common.change'),
'caution',
);
if (!isConfirmed) return;
@ -444,7 +444,7 @@ function ProfileViewer() {
title={room?.name ?? ''}
onAfterClose={handleAfterClose}
onRequestClose={closeDialog}
contentOptions={<IconButton src={CrossIC} onClick={closeDialog} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={closeDialog} tooltip={t('common.close')} />}
>
{roomId ? renderProfile() : <div />}
</Dialog>

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './PublicRooms.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { selectRoom, selectTab } from '../../../client/action/navigation';
@ -18,9 +19,7 @@ import RoomTile from '../../molecules/room-tile/RoomTile';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const SEARCH_LIMIT = 20;
@ -59,7 +58,7 @@ function TryJoinWithAlias({ alias, onRequestClose }) {
} catch (e) {
setStatus({
isJoining: false,
error: t("Organisms.PublicRooms.could_not_join_alias", {alias: alias}),
error: t('Organisms.PublicRooms.could_not_join_alias', { alias }),
roomId: null,
tempRoomId: null,
});
@ -69,16 +68,16 @@ function TryJoinWithAlias({ alias, onRequestClose }) {
return (
<div className="try-join-with-alias">
{status.roomId === null && !status.isJoining && status.error === null && (
<Button onClick={() => joinWithAlias()}>{t("Organisms.PublicRooms.try_joining_alias", {alias: alias})}</Button>
<Button onClick={() => joinWithAlias()}>{t('Organisms.PublicRooms.try_joining_alias', { alias })}</Button>
)}
{status.isJoining && (
<>
<Spinner size="small" />
<Text>{t("Organisms.PublicRooms.joining_alias", {alias: alias})}</Text>
<Text>{t('Organisms.PublicRooms.joining_alias', { alias })}</Text>
</>
)}
{status.roomId !== null && (
<Button onClick={() => { onRequestClose(); selectRoom(status.roomId); }}>{t("common.open")}</Button>
<Button onClick={() => { onRequestClose(); selectRoom(status.roomId); }}>{t('common.open')}</Button>
)}
{status.error !== null && <Text variant="b2"><span style={{ color: 'var(--bg-danger)' }}>{status.error}</span></Text>}
</div>
@ -147,14 +146,14 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
if (totalRooms.length === 0) {
updateSearchQuery({
error: inputRoomName === ''
? t("Organisms.PublicRooms.no_public_rooms", {homeserver: inputHs})
: t("Organisms.PublicRooms.no_result_found", {homeserver: inputHs, input: inputRoomName}),
? t('Organisms.PublicRooms.no_public_rooms', { homeserver: inputHs })
: t('Organisms.PublicRooms.no_result_found', { homeserver: inputHs, input: inputRoomName }),
alias: isInputAlias ? inputRoomName : null,
});
}
} catch (e) {
updatePublicRooms([]);
let err = t("errors.generic");
let err = t('errors.generic');
if (e?.httpStatus >= 400 && e?.httpStatus < 500) {
err = e.message;
}
@ -213,8 +212,8 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
desc={typeof room.topic === 'string' ? room.topic : null}
options={(
<>
{isJoined && <Button onClick={() => handleViewRoom(room.room_id)}>{t("common.open")}</Button>}
{!isJoined && (joiningRooms.has(room.room_id) ? <Spinner size="small" /> : <Button onClick={() => joinRoom(room.aliases?.[0] || room.room_id)} variant="primary">{t("commom.join")}</Button>)}
{isJoined && <Button onClick={() => handleViewRoom(room.room_id)}>{t('common.open')}</Button>}
{!isJoined && (joiningRooms.has(room.room_id) ? <Spinner size="small" /> : <Button onClick={() => joinRoom(room.aliases?.[0] || room.room_id)} variant="primary">{t('commom.join')}</Button>)}
</>
)}
/>
@ -225,17 +224,17 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
return (
<PopupWindow
isOpen={isOpen}
title={t("Organisms.PublicRooms.title")}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t("common.close")} />}
title={t('Organisms.PublicRooms.title')}
contentOptions={<IconButton src={CrossIC} onClick={onRequestClose} tooltip={t('common.close')} />}
onRequestClose={onRequestClose}
>
<div className="public-rooms">
<form className="public-rooms__form" onSubmit={(e) => { e.preventDefault(); searchRooms(); }}>
<div className="public-rooms__input-wrapper">
<Input value={searchTerm} forwardRef={roomNameRef} label={t("Organisms.PublicRooms.search_room_name_alias")} />
<Input forwardRef={hsRef} value={userId.slice(userId.indexOf(':') + 1)} label={t("common.homeserver")} required />
<Input value={searchTerm} forwardRef={roomNameRef} label={t('Organisms.PublicRooms.search_room_name_alias')} />
<Input forwardRef={hsRef} value={userId.slice(userId.indexOf(':') + 1)} label={t('common.homeserver')} required />
</div>
<Button disabled={isSearching} iconSrc={HashSearchIC} variant="primary" type="submit">{t("Organisms.PublicRooms.search_button")}</Button>
<Button disabled={isSearching} iconSrc={HashSearchIC} variant="primary" type="submit">{t('Organisms.PublicRooms.search_button')}</Button>
</form>
<div className="public-rooms__search-status">
{
@ -244,13 +243,13 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
? (
<div className="flex--center">
<Spinner size="small" />
<Text variant="b2">{t("Organisms.PublicRooms.loading", {homeserver: searchQuery.homeserver})}</Text>
<Text variant="b2">{t('Organisms.PublicRooms.loading', { homeserver: searchQuery.homeserver })}</Text>
</div>
)
: (
<div className="flex--center">
<Spinner size="small" />
<Text variant="b2">{t("Organisms.PublicRooms.searching", {homeserver: searchQuery.homeserver, query: searchQuery.name})}</Text>
<Text variant="b2">{t('Organisms.PublicRooms.searching', { homeserver: searchQuery.homeserver, query: searchQuery.name })}</Text>
</div>
)
)
@ -258,8 +257,8 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
{
typeof searchQuery.name !== 'undefined' && !isSearching && (
searchQuery.name === ''
? <Text variant="b2">{t("Organisms.PublicRooms.result_title", {homeserver: searchQuery.homeserver})}</Text>
: <Text variant="b2">{t("Organisms.PublicRooms.search_result_title", {homeserver: searchQuery.homeserver, query: searchQuery.name})}</Text>
? <Text variant="b2">{t('Organisms.PublicRooms.result_title', { homeserver: searchQuery.homeserver })}</Text>
: <Text variant="b2">{t('Organisms.PublicRooms.search_result_title', { homeserver: searchQuery.homeserver, query: searchQuery.name })}</Text>
)
}
{ searchQuery.error && (
@ -279,7 +278,7 @@ function PublicRooms({ isOpen, searchTerm, onRequestClose }) {
{ publicRooms.length !== 0 && publicRooms.length % SEARCH_LIMIT === 0 && (
<div className="public-rooms__view-more">
{ isViewMore !== true && (
<Button onClick={() => searchRooms(true)}>{t("commom.view_more")}</Button>
<Button onClick={() => searchRooms(true)}>{t('commom.view_more')}</Button>
)}
{ isViewMore && <Spinner /> }
</div>

View file

@ -4,6 +4,7 @@ import React, {
import PropTypes from 'prop-types';
import './PeopleDrawer.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import { getPowerLabel, getUsernameOfRoomMember } from '../../../util/matrixUtil';
import colorMXID from '../../../util/colorMXID';
@ -25,8 +26,7 @@ import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
import SearchIC from '../../../../public/res/ic/outlined/search.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function simplyfiMembers(members) {
const mx = initMatrix.matrixClient;
@ -134,11 +134,11 @@ function PeopleDrawer({ roomId }) {
<Header>
<TitleWrapper>
<Text variant="s1" primary>
{t("Organisms.PeopleDrawer.title")}
<Text className="people-drawer__member-count" variant="b3">{t("Organisms.PeopleDrawer.members", {count: room.getJoinedMemberCount()})}</Text>
{t('Organisms.PeopleDrawer.title')}
<Text className="people-drawer__member-count" variant="b3">{t('Organisms.PeopleDrawer.members', { count: room.getJoinedMemberCount() })}</Text>
</Text>
</TitleWrapper>
<IconButton onClick={() => openInviteUser(roomId)} tooltip={t("Organisms.PeopleDrawer.invite_tooltip")} src={AddUserIC} disabled={!canInvite} />
<IconButton onClick={() => openInviteUser(roomId)} tooltip={t('Organisms.PeopleDrawer.invite_tooltip')} src={AddUserIC} disabled={!canInvite} />
</Header>
<div className="people-drawer__content-wrapper">
<div className="people-drawer__scrollable">
@ -155,7 +155,7 @@ function PeopleDrawer({ roomId }) {
return getSegmentIndex[membership];
})()
}
segments={[{ text: t("Organisms.PeopleDrawer.joined")}, { text: t("Organisms.PeopleDrawer.invited") }, { text: t("Organisms.PeopleDrawer.banned") }]}
segments={[{ text: t('Organisms.PeopleDrawer.joined') }, { text: t('Organisms.PeopleDrawer.invited') }, { text: t('Organisms.PeopleDrawer.banned') }]}
onSelect={(index) => {
const selectSegment = [
() => setMembership('join'),
@ -181,7 +181,7 @@ function PeopleDrawer({ roomId }) {
(searchedMembers?.data.length === 0 || memberList.length === 0)
&& (
<div className="people-drawer__noresult">
<Text variant="b2">{t("Organisms.PeopleDrawer.search_no_results")}</Text>
<Text variant="b2">{t('Organisms.PeopleDrawer.search_no_results')}</Text>
</div>
)
}
@ -191,7 +191,7 @@ function PeopleDrawer({ roomId }) {
&& memberList.length > itemCount
&& searchedMembers === null
&& (
<Button onClick={loadMorePeople}>{t("Organisms.PeopleDrawer.view_more")}</Button>
<Button onClick={loadMorePeople}>{t('Organisms.PeopleDrawer.view_more')}</Button>
)
}
</div>
@ -201,7 +201,7 @@ function PeopleDrawer({ roomId }) {
<div className="people-drawer__sticky">
<form onSubmit={(e) => e.preventDefault()} className="people-search">
<RawIcon size="small" src={SearchIC} />
<Input forwardRef={searchRef} type="text" onChange={handleSearch} placeholder={t("Organisms.PeopleDrawer.placeholder")} required />
<Input forwardRef={searchRef} type="text" onChange={handleSearch} placeholder={t('Organisms.PeopleDrawer.placeholder')} required />
{
searchedMembers !== null
&& <IconButton onClick={handleSearch} size="small" src={CrossIC} />

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomSettings.scss';
import { useTranslation } from 'react-i18next';
import { blurOnBubbling } from '../../atoms/button/script';
import initMatrix from '../../../client/initMatrix';
@ -38,9 +39,7 @@ import ChevronTopIC from '../../../../public/res/ic/outlined/chevron-top.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
import '../../i18n';
const tabText = {
GENERAL: 'General',
@ -94,9 +93,9 @@ function GeneralSettings({ roomId }) {
variant="danger"
onClick={async () => {
const isConfirmed = await confirmDialog(
t("Organisms.RoomSettings.leave_room"),
t("Organisms.RoomSettings.leave_room_confirm_message", {room_name: room.name}),
t("Organisms.RoomSettings.leave_room_confirm_button"),
t('Organisms.RoomSettings.leave_room'),
t('Organisms.RoomSettings.leave_room_confirm_message', { room_name: room.name }),
t('Organisms.RoomSettings.leave_room_confirm_button'),
'danger',
);
if (!isConfirmed) return;
@ -108,15 +107,15 @@ function GeneralSettings({ roomId }) {
</MenuItem>
</div>
<div className="room-settings__card">
<MenuHeader>{t("Organisms.RoomSettings.notification_header")}</MenuHeader>
<MenuHeader>{t('Organisms.RoomSettings.notification_header')}</MenuHeader>
<RoomNotification roomId={roomId} />
</div>
<div className="room-settings__card">
<MenuHeader>{t("Organisms.RoomSettings.visibility_header")}</MenuHeader>
<MenuHeader>{t('Organisms.RoomSettings.visibility_header')}</MenuHeader>
<RoomVisibility roomId={roomId} />
</div>
<div className="room-settings__card">
<MenuHeader>{t("Organisms.RoomSettings.address_header")}</MenuHeader>
<MenuHeader>{t('Organisms.RoomSettings.address_header')}</MenuHeader>
<RoomAliases roomId={roomId} />
</div>
</>
@ -128,14 +127,15 @@ GeneralSettings.propTypes = {
};
function SecuritySettings({ roomId }) {
const { t } = useTranslation();
return (
<>
<div className="room-settings__card">
<MenuHeader>{t("Organisms.RoomSettings.encryption_header")}</MenuHeader>
<MenuHeader>{t('Organisms.RoomSettings.encryption_header')}</MenuHeader>
<RoomEncryption roomId={roomId} />
</div>
<div className="room-settings__card">
<MenuHeader>{t("Organisms.RoomSettings.message_history_header")}</MenuHeader>
<MenuHeader>{t('Organisms.RoomSettings.message_history_header')}</MenuHeader>
<RoomHistoryVisibility roomId={roomId} />
</div>
</>
@ -149,6 +149,7 @@ function RoomSettings({ roomId }) {
const [, forceUpdate] = useForceUpdate();
const [selectedTab, setSelectedTab] = useState(tabItems[0]);
const room = initMatrix.matrixClient.getRoom(roomId);
const { t } = useTranslation();
const handleTabChange = (tabItem) => {
setSelectedTab(tabItem);
@ -187,7 +188,12 @@ function RoomSettings({ roomId }) {
<TitleWrapper>
<Text variant="s1" weight="medium" primary>
{`${room.name}`}
<span style={{ color: 'var(--tc-surface-low)' }}> {t("Organisms.RoomSettings.room_settings_subtitle")}</span>
<span style={{ color: 'var(--tc-surface-low)' }}>
{' '}
{' '}
{t('Organisms.RoomSettings.room_settings_subtitle')}
</span>
</Text>
</TitleWrapper>
<RawIcon size="small" src={ChevronTopIC} />

View file

@ -8,6 +8,7 @@ import PropTypes from 'prop-types';
import './RoomViewContent.scss';
import dateFormat from 'dateformat';
import { useTranslation, Trans } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -29,9 +30,7 @@ import { parseTimelineChange } from './common';
import TimelineScroll from './TimelineScroll';
import EventLimit from './EventLimit';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { Trans } from 'react-i18next';
import '../../i18n';
const PAG_LIMIT = 30;
const MAX_MSG_DIFF_MINUTES = 5;
@ -68,30 +67,30 @@ function RoomIntroContainer({ event, timeline }) {
let avatarSrc = room.getAvatarUrl(mx.baseUrl, 80, 80, 'crop');
avatarSrc = isDM ? room.getAvatarFallbackMember()?.getAvatarUrl(mx.baseUrl, 80, 80, 'crop') : avatarSrc;
const heading = isDM ? room.name : t("Organisms.RoomViewContent.welcome_to_room", {room_name: room.name});
const heading = isDM ? room.name : t('Organisms.RoomViewContent.welcome_to_room', { room_name: room.name });
const topic = twemojify(roomTopic || '', undefined, true);
const nameJsx = twemojify(room.name);
const desc = isDM
? (
<>
<Trans
i18nKey={"Organisms.RoomViewContent.beginning_dm"}
values={{user_name: nameJsx}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomViewContent.beginning_dm"
values={{ user_name: nameJsx }}
components={{ bold: <b /> }}
/>
{topic == "" ? "" : " - "}
{topic == '' ? '' : ' - '}
{topic }
</>
)
: (
<>
<Trans
i18nKey={"Organisms.RoomViewContent.beginning_room"}
values={{room_name: nameJsx}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomViewContent.beginning_room"
values={{ room_name: nameJsx }}
components={{ bold: <b /> }}
/>
{topic == "" ? "" : " - "}
{topic == '' ? '' : ' - '}
{topic}
</>
);
@ -112,7 +111,14 @@ function RoomIntroContainer({ event, timeline }) {
name={room.name}
heading={twemojify(heading)}
desc={desc}
time={event ? t("Organisms.RoomViewContent.created_on", {date: event.getDate(), formatParams: { date: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'}}}) : null}
time={event ? t('Organisms.RoomViewContent.created_on', {
date: event.getDate(),
formatParams: {
date: {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',
},
},
}) : null}
/>
);
}
@ -539,7 +545,7 @@ function RoomViewContent({ eventId, roomTimeline }) {
&& readUptoEvent.getTs() < mEvent.getTs());
if (unreadDivider) {
isNewEvent = true;
tl.push(<Divider key={`new-${mEvent.getId()}`} variant="positive" text={t("Organisms.RoomViewContent.new_messages")} />);
tl.push(<Divider key={`new-${mEvent.getId()}`} variant="positive" text={t('Organisms.RoomViewContent.new_messages')} />);
itemCountIndex += 1;
if (jumpToItemIndex === -1) jumpToItemIndex = itemCountIndex;
}

View file

@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomViewFloating.scss';
import { useTranslation, Trans } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -18,11 +19,7 @@ import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
import { getUsername, getUsernameOfRoomMember } from '../../../util/matrixUtil';
import { getUsersActionJsx } from './common';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { Trans } from 'react-i18next';
import '../../i18n';
function useJumpToEvent(roomTimeline) {
const [eventId, setEventId] = useState(null);
@ -94,14 +91,13 @@ function useScrollToBottom(roomTimeline) {
function RoomViewFloating({
roomId, roomTimeline,
}) {
const { t } = useTranslation();
const [isJumpToEvent, jumpToEvent, cancelJumpToEvent] = useJumpToEvent(roomTimeline);
const [typingMembers] = useTypingMembers(roomTimeline);
const [isAtBottom, setIsAtBottom] = useScrollToBottom(roomTimeline);
const room = initMatrix.matrixClient.getRoom(roomId)
const room = initMatrix.matrixClient.getRoom(roomId);
const getUserDisplayName = (userId) => {
if (room?.getMember(userId)) return getUsernameOfRoomMember(room.getMember(userId));
@ -113,20 +109,20 @@ function RoomViewFloating({
setIsAtBottom(true);
};
console.log(typingMembers)
console.log(typingMembers);
let typingMemberValues = [...typingMembers];
const typingMemberValues = [...typingMembers];
console.log(typingMemberValues)
console.log(typingMemberValues);
return (
<>
<div className={`room-view__unread ${isJumpToEvent ? 'room-view__unread--open' : ''}`}>
<Button iconSrc={MessageUnreadIC} onClick={jumpToEvent} variant="primary">
<Text variant="b3" weight="medium">{t("Organisms.RoomViewFloating.jump_unread")}</Text>
<Text variant="b3" weight="medium">{t('Organisms.RoomViewFloating.jump_unread')}</Text>
</Button>
<Button iconSrc={TickMarkIC} onClick={cancelJumpToEvent} variant="primary">
<Text variant="b3" weight="bold">{t("Organisms.RoomViewFloating.mark_read")}</Text>
<Text variant="b3" weight="bold">{t('Organisms.RoomViewFloating.mark_read')}</Text>
</Button>
</div>
<div className={`room-view__typing${typingMembers.size > 0 ? ' room-view__typing--open' : ''}`}>
@ -139,15 +135,15 @@ function RoomViewFloating({
user_one: twemojify(getUserDisplayName(typingMemberValues?.[0])),
user_two: twemojify(getUserDisplayName(typingMemberValues?.[1])),
user_three: twemojify(getUserDisplayName(typingMemberValues?.[2])),
user_four: twemojify(getUserDisplayName(typingMemberValues?.[3]))
user_four: twemojify(getUserDisplayName(typingMemberValues?.[3])),
}}
components={{bold: <b/>}}
components={{ bold: <b /> }}
/>
</Text>
</div>
<div className={`room-view__STB${isAtBottom ? '' : ' room-view__STB--open'}`}>
<Button iconSrc={MessageIC} onClick={handleScrollToBottom}>
<Text variant="b3" weight="medium">{t("Organisms.RoomViewFloating.jump_latest")}</Text>
<Text variant="b3" weight="medium">{t('Organisms.RoomViewFloating.jump_latest')}</Text>
</Button>
</div>
</>

View file

@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './RoomViewHeader.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import { blurOnBubbling } from '../../atoms/button/script';
@ -29,8 +30,7 @@ import BackArrowIC from '../../../../public/res/ic/outlined/chevron-left.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function RoomViewHeader({ roomId }) {
const [, forceUpdate] = useForceUpdate();
@ -98,12 +98,12 @@ function RoomViewHeader({ roomId }) {
</TitleWrapper>
<RawIcon src={ChevronBottomIC} />
</button>
<IconButton onClick={() => toggleRoomSettings(tabText.SEARCH)} tooltip={t("Organisms.RoomViewHeader.search_tooltip")} src={SearchIC} />
<IconButton className="room-header__drawer-btn" onClick={togglePeopleDrawer} tooltip={t("Organisms.RoomViewHeader.people_tooltip")} src={UserIC} />
<IconButton className="room-header__members-btn" onClick={() => toggleRoomSettings(tabText.MEMBERS)} tooltip={t("Organisms.RoomViewHeader.members_tooltip")} src={UserIC} />
<IconButton onClick={() => toggleRoomSettings(tabText.SEARCH)} tooltip={t('Organisms.RoomViewHeader.search_tooltip')} src={SearchIC} />
<IconButton className="room-header__drawer-btn" onClick={togglePeopleDrawer} tooltip={t('Organisms.RoomViewHeader.people_tooltip')} src={UserIC} />
<IconButton className="room-header__members-btn" onClick={() => toggleRoomSettings(tabText.MEMBERS)} tooltip={t('Organisms.RoomViewHeader.members_tooltip')} src={UserIC} />
<IconButton
onClick={openRoomOptions}
tooltip={t("common.options")}
tooltip={t('common.options')}
src={VerticalMenuIC}
/>
</Header>

View file

@ -5,6 +5,7 @@ import './RoomViewInput.scss';
import TextareaAutosize from 'react-autosize-textarea';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import settings from '../../../client/state/settings';
@ -30,8 +31,7 @@ import MarkdownIC from '../../../../public/res/ic/outlined/markdown.svg';
import FileIC from '../../../../public/res/ic/outlined/file.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const CMD_REGEX = /(^\/|:|@)(\S*)$/;
let isTyping = false;
@ -86,7 +86,7 @@ function RoomViewInput({
function uploadingProgress(myRoomId, { loaded, total }) {
if (myRoomId !== roomId) return;
const progressPer = Math.round((loaded * 100) / total);
uploadProgressRef.current.textContent = t("Organisms.RoomViewInput.upload_progress", {progress: bytesToSize(loaded), total:bytesToSize(total), percent: progressPer});
uploadProgressRef.current.textContent = t('Organisms.RoomViewInput.upload_progress', { progress: bytesToSize(loaded), total: bytesToSize(total), percent: progressPer });
inputBaseRef.current.style.backgroundImage = `linear-gradient(90deg, var(--bg-surface-hover) ${progressPer}%, var(--bg-surface-low) ${progressPer}%)`;
}
function clearAttachment(myRoomId) {
@ -133,9 +133,7 @@ function RoomViewInput({
}
function firedCmd(cmdData) {
const msg = textAreaRef.current.value;
textAreaRef.current.value = replaceCmdWith(
msg, cmdCursorPos, typeof cmdData?.replace !== 'undefined' ? cmdData.replace : '',
);
textAreaRef.current.value = replaceCmdWith(msg, cmdCursorPos, typeof cmdData?.replace !== 'undefined' ? cmdData.replace : '');
deactivateCmd();
}
@ -316,8 +314,8 @@ function RoomViewInput({
<Text className="room-input__alert">
{
tombstoneEvent
? tombstoneEvent.getContent()?.body ?? t("Organisms.RoomViewInput.tombstone_replaced")
: t("Organisms.RoomViewInput.tombstone_permission_denied")
? tombstoneEvent.getContent()?.body ?? t('Organisms.RoomViewInput.tombstone_replaced')
: t('Organisms.RoomViewInput.tombstone_permission_denied')
}
</Text>
);
@ -338,7 +336,7 @@ function RoomViewInput({
onChange={handleMsgTyping}
onPaste={handlePaste}
onKeyDown={handleKeyDown}
placeholder={t("Organisms.RoomViewInput.send_message_placeholder")}
placeholder={t('Organisms.RoomViewInput.send_message_placeholder')}
/>
</Text>
</ScrollView>
@ -352,10 +350,10 @@ function RoomViewInput({
cords.y -= 250;
openEmojiBoard(cords, addEmoji);
}}
tooltip={t("Organisms.RoomViewInput.emoji_tooltip")}
tooltip={t('Organisms.RoomViewInput.emoji_tooltip')}
src={EmojiIC}
/>
<IconButton onClick={sendMessage} tooltip={t("common.send")} src={SendIC} />
<IconButton onClick={sendMessage} tooltip={t('common.send')} src={SendIC} />
</div>
</>
);
@ -373,7 +371,7 @@ function RoomViewInput({
</div>
<div className="room-attachment__info">
<Text variant="b1">{attachment.name}</Text>
<Text variant="b3"><span ref={uploadProgressRef}>{t("Organisms.RoomViewInput.file_size", {size: bytesToSize(attachment.size)})}</span></Text>
<Text variant="b3"><span ref={uploadProgressRef}>{t('Organisms.RoomViewInput.file_size', { size: bytesToSize(attachment.size) })}</span></Text>
</div>
</div>
);
@ -388,7 +386,7 @@ function RoomViewInput({
setReplyTo(null);
}}
src={CrossIC}
tooltip={t("Organisms.RoomViewInput.cancel_reply_tooltip")}
tooltip={t('Organisms.RoomViewInput.cancel_reply_tooltip')}
size="extra-small"
/>
<MessageReply

View file

@ -1,173 +1,151 @@
import React from 'react';
import { Trans } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
import { getUsername, getUsernameOfRoomMember } from '../../../util/matrixUtil';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import { Trans } from 'react-i18next';
import '../../i18n';
function getTimelineJSXMessages() {
return {
join(user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_joined"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_joined"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
leave(user, reason) {
const reasonMsg = (typeof reason === 'string') ? `: ${reason}` : '';
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_left"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_left"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
invite(inviter, user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_invited"}
values={{user_name: twemojify(user), inviter_name: twemojify(inviter)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_invited"
values={{ user_name: twemojify(user), inviter_name: twemojify(inviter) }}
components={{ bold: <b /> }}
/>
</>
);
},
cancelInvite(inviter, user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.invite_cancelled"}
values={{user_name: twemojify(user), inviter_name: twemojify(inviter)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.invite_cancelled"
values={{ user_name: twemojify(user), inviter_name: twemojify(inviter) }}
components={{ bold: <b /> }}
/>
</>
);
},
rejectInvite(user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.invite_rejected"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.invite_rejected"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
kick(actor, user, reason) {
const reasonMsg = (typeof reason === 'string') ? `${reason}` : '';
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_kicked"}
values={{user_name: twemojify(user), actor: twemojify(actor), reason: twemojify(reasonMsg)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_kicked"
values={{
user_name: twemojify(user),
actor: twemojify(actor),
reason: twemojify(reasonMsg),
}}
components={{ bold: <b /> }}
/>
</>
);
},
ban(actor, user, reason) {
const reasonMsg = (typeof reason === 'string') ? `${reason}` : '';
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_banned"}
values={{user_name: twemojify(user), actor: twemojify(actor), reason: twemojify(reasonMsg)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_banned"
values={{
user_name: twemojify(user),
actor: twemojify(actor),
reason: twemojify(reasonMsg),
}}
components={{ bold: <b /> }}
/>
</>
);
},
unban(actor, user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.user_unbanned"}
values={{user_name: twemojify(user), actor: twemojify(actor)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.user_unbanned"
values={{ user_name: twemojify(user), actor: twemojify(actor) }}
components={{ bold: <b /> }}
/>
</>
);
},
avatarSets(user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.avatar_set"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.avatar_set"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
avatarChanged(user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.avatar_changed"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.avatar_changed"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
avatarRemoved(user) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.avatar_removed"}
values={{user_name: twemojify(user)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.avatar_removed"
values={{ user_name: twemojify(user) }}
components={{ bold: <b /> }}
/>
</>
);
},
nameSets(user, newName) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.name_set"}
values={{user_name: twemojify(user), new_name: twemojify(newName)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.name_set"
values={{ user_name: twemojify(user), new_name: twemojify(newName) }}
components={{ bold: <b /> }}
/>
</>
);
},
nameChanged(user, newName) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.name_changed"}
values={{user_name: twemojify(user), new_name: twemojify(newName)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.name_changed"
values={{ user_name: twemojify(user), new_name: twemojify(newName) }}
components={{ bold: <b /> }}
/>
</>
);
},
nameRemoved(user, lastName) {
return (
<>
<Trans
i18nKey={"Organisms.RoomCommon.name_removed"}
values={{user_name: twemojify(user), new_name: twemojify(newName)}}
components={{bold: <b/>}}
i18nKey="Organisms.RoomCommon.name_removed"
values={{ user_name: twemojify(user), new_name: twemojify(lastName) }}
components={{ bold: <b /> }}
/>
</>
);
},
};

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from 'react';
import './Search.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
@ -20,8 +21,7 @@ import RoomSelector from '../../molecules/room-selector/RoomSelector';
import SearchIC from '../../../../public/res/ic/outlined/search.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function useVisiblityToggle(setResult) {
const [isOpen, setIsOpen] = useState(false);
@ -212,12 +212,12 @@ function Search() {
size="small"
>
<div className="search-dialog">
<form className="search-dialog__input" onSubmit={(e) => { e.preventDefault(); openFirstResult()}}>
<form className="search-dialog__input" onSubmit={(e) => { e.preventDefault(); openFirstResult(); }}>
<RawIcon src={SearchIC} size="small" />
<Input
onChange={handleOnChange}
forwardRef={searchRef}
placeholder={t("common.search")}
placeholder={t('common.search')}
/>
<IconButton size="small" src={CrossIC} type="reset" onClick={handleCross} tabIndex={-1} />
</form>
@ -229,7 +229,7 @@ function Search() {
</ScrollView>
</div>
<div className="search-dialog__footer">
<Text variant="b3">{t("Organisms.Search.description")}</Text>
<Text variant="b3">{t('Organisms.Search.description')}</Text>
</div>
</div>
</RawModal>

View file

@ -12,7 +12,7 @@ import Spinner from '../../atoms/spinner/Spinner';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import '../../i18n';
import { useTranslation } from 'react-i18next';
let lastUsedPassword;

View file

@ -20,7 +20,7 @@ import { authRequest } from './AuthRequest';
import { useCrossSigningStatus } from '../../hooks/useCrossSigningStatus';
import '../../i18n.jsx'
import '../../i18n';
import { useTranslation } from 'react-i18next';

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import './DeviceManage.scss';
import dateFormat from 'dateformat';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import { isCrossVerified } from '../../../util/matrixUtil';
import { openReusableDialog, openEmojiVerification } from '../../../client/action/navigation';
@ -27,9 +28,7 @@ import { useDeviceList } from '../../hooks/useDeviceList';
import { useCrossSigningStatus } from '../../hooks/useCrossSigningStatus';
import { accessSecretStorage } from './SecretStorageAccess';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const promptDeviceName = async (deviceName) => new Promise((resolve) => {
let isCompleted = false;
@ -45,17 +44,17 @@ const promptDeviceName = async (deviceName) => new Promise((resolve) => {
};
return (
<form className="device-manage__rename" onSubmit={handleSubmit}>
<Input value={deviceName} label={t("Organisms.DeviceManage.edit_session_name_subtitle")} name="session" />
<Input value={deviceName} label={t('Organisms.DeviceManage.edit_session_name_subtitle')} name="session" />
<div className="device-manage__rename-btn">
<Button variant="primary" type="submit">{t("common.save")}</Button>
<Button onClick={() => onComplete(null)}>{t("common.cancel")}</Button>
<Button variant="primary" type="submit">{t('common.save')}</Button>
<Button onClick={() => onComplete(null)}>{t('common.cancel')}</Button>
</div>
</form>
);
};
openReusableDialog(
<Text variant="s1" weight="medium">{t("Organisms.DeviceManage.edit_session_name_title")}</Text>,
<Text variant="s1" weight="medium">{t('Organisms.DeviceManage.edit_session_name_title')}</Text>,
(requestClose) => renderContent((name) => {
isCompleted = true;
resolve(name);
@ -95,17 +94,17 @@ function DeviceManage() {
};
return (
<form className="device-manage__rename" onSubmit={handleSubmit}>
<Input value={deviceName} label={t("Organisms.DeviceManage.edit_session_name_subtitle")} name="session" />
<Input value={deviceName} label={t('Organisms.DeviceManage.edit_session_name_subtitle')} name="session" />
<div className="device-manage__rename-btn">
<Button variant="primary" type="submit">{t("common.save")}</Button>
<Button onClick={() => onComplete(null)}>{t("common.cancel")}</Button>
<Button variant="primary" type="submit">{t('common.save')}</Button>
<Button onClick={() => onComplete(null)}>{t('common.cancel')}</Button>
</div>
</form>
);
};
openReusableDialog(
<Text variant="s1" weight="medium">{t("Organisms.DeviceManage.edit_session_name_title")}</Text>,
<Text variant="s1" weight="medium">{t('Organisms.DeviceManage.edit_session_name_title')}</Text>,
(requestClose) => renderContent((name) => {
isCompleted = true;
resolve(name);
@ -132,7 +131,7 @@ function DeviceManage() {
<div className="device-manage">
<div className="device-manage__loading">
<Spinner size="small" />
<Text>{t("Organisms.DeviceManage.loading_devices")}</Text>
<Text>{t('Organisms.DeviceManage.loading_devices')}</Text>
</div>
</div>
);
@ -155,14 +154,14 @@ function DeviceManage() {
const handleRemove = async (device) => {
const isConfirmed = await confirmDialog(
t("Organisms.DeviceManage.logout_device_title", {device: device.display_name}),
t("Organisms.DeviceManage.logout_device_message", {device: device.display_name}),
t("Organisms.DeviceManage.logout_device_confirm"),
t('Organisms.DeviceManage.logout_device_title', { device: device.display_name }),
t('Organisms.DeviceManage.logout_device_message', { device: device.display_name }),
t('Organisms.DeviceManage.logout_device_confirm'),
'danger',
);
if (!isConfirmed) return;
addToProcessing(device);
await authRequest(t("Organisms.DeviceManage.logout_device_title", {device: device.display_name}), async (auth) => {
await authRequest(t('Organisms.DeviceManage.logout_device_title', { device: device.display_name }), async (auth) => {
await mx.deleteDevice(device.device_id, auth);
});
@ -171,7 +170,7 @@ function DeviceManage() {
};
const verifyWithKey = async (device) => {
const keyData = await accessSecretStorage(t("Organisms.DeviceManage.session_verification_title"));
const keyData = await accessSecretStorage(t('Organisms.DeviceManage.session_verification_title'));
if (!keyData) return;
addToProcessing(device);
await mx.checkOwnCrossSigningTrust();
@ -205,7 +204,7 @@ function DeviceManage() {
<Text style={{ color: isVerified !== false ? '' : 'var(--tc-danger-high)' }}>
{displayName}
<Text variant="b3" span>{`${displayName ? ' — ' : ''}${deviceId}`}</Text>
{isCurrentDevice && <Text span className="device-manage__current-label" variant="b3">{t("Organisms.DeviceManage.current_device_label")}</Text>}
{isCurrentDevice && <Text span className="device-manage__current-label" variant="b3">{t('Organisms.DeviceManage.current_device_label')}</Text>}
</Text>
)}
options={
@ -213,9 +212,9 @@ function DeviceManage() {
? <Spinner size="small" />
: (
<>
{(isCSEnabled && canVerify) && <Button onClick={() => verify(deviceId, isCurrentDevice)} variant="positive">{t("Organisms.DeviceManage.verify_session_button")}</Button>}
<IconButton size="small" onClick={() => handleRename(device)} src={PencilIC} tooltip={t("Organisms.DeviceManage.edit_session_name_tooltip")} />
<IconButton size="small" onClick={() => handleRemove(device)} src={BinIC} tooltip={t("Organisms.DeviceManage.logout_device_tooltip")}/>
{(isCSEnabled && canVerify) && <Button onClick={() => verify(deviceId, isCurrentDevice)} variant="positive">{t('Organisms.DeviceManage.verify_session_button')}</Button>}
<IconButton size="small" onClick={() => handleRename(device)} src={PencilIC} tooltip={t('Organisms.DeviceManage.edit_session_name_tooltip')} />
<IconButton size="small" onClick={() => handleRemove(device)} src={BinIC} tooltip={t('Organisms.DeviceManage.logout_device_tooltip')} />
</>
)
}
@ -256,46 +255,46 @@ function DeviceManage() {
return (
<div className="device-manage">
<div>
<MenuHeader>{t("Organisms.DeviceManage.unverified_sessions_title")}</MenuHeader>
<MenuHeader>{t('Organisms.DeviceManage.unverified_sessions_title')}</MenuHeader>
{!isCSEnabled && (
<div style={{ padding: 'var(--sp-extra-tight) var(--sp-normal)' }}>
<InfoCard
rounded
variant="caution"
iconSrc={InfoIC}
title={t("Organisms.DeviceManage.setup_cross_signing_message")}
title={t('Organisms.DeviceManage.setup_cross_signing_message')}
/>
</div>
)}
{
unverified.length > 0
? unverified.map((device) => renderDevice(device, false))
: <Text className="device-manage__info">{t("Organisms.DeviceManage.unverified_sessions_none")}</Text>
: <Text className="device-manage__info">{t('Organisms.DeviceManage.unverified_sessions_none')}</Text>
}
</div>
{noEncryption.length > 0 && (
<div>
<MenuHeader>{t("Organisms.DeviceManage.unencrypted_sessions_title")}</MenuHeader>
<MenuHeader>{t('Organisms.DeviceManage.unencrypted_sessions_title')}</MenuHeader>
{noEncryption.map((device) => renderDevice(device, null))}
</div>
)}
<div>
<MenuHeader>{t("Organisms.DeviceManage.verified_sessions_title")}</MenuHeader>
<MenuHeader>{t('Organisms.DeviceManage.verified_sessions_title')}</MenuHeader>
{
verified.length > 0
? verified.map((device, index) => {
if (truncated && index >= TRUNCATED_COUNT) return null;
return renderDevice(device, true);
})
: <Text className="device-manage__info">{t("Organisms.DeviceManage.verified_sessions_none")}</Text>
: <Text className="device-manage__info">{t('Organisms.DeviceManage.verified_sessions_none')}</Text>
}
{ verified.length > TRUNCATED_COUNT && (
<Button className="device-manage__info" onClick={() => setTruncated(!truncated)}>
{t(truncated ? "common.view_more" : "common.view_less")}
{t(truncated ? 'common.view_more' : 'common.view_less')}
</Button>
)}
{ deviceList.length > 0 && (
<Text className="device-manage__info" variant="b3">{t("Organisms.DeviceManage.session_name_privacy_message")}</Text>
<Text className="device-manage__info" variant="b3">{t('Organisms.DeviceManage.session_name_privacy_message')}</Text>
)}
</div>
</div>

View file

@ -24,7 +24,7 @@ import DownloadIC from '../../../../public/res/ic/outlined/download.svg';
import { useStore } from '../../hooks/useStore';
import { useCrossSigningStatus } from '../../hooks/useCrossSigningStatus';
import '../../i18n.jsx'
import '../../i18n';
import { useTranslation } from 'react-i18next';

View file

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import './SecretStorageAccess.scss';
import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import { openReusableDialog } from '../../../client/action/navigation';
import { getDefaultSSKey, getSSKeyInfo } from '../../../util/matrixUtil';
@ -13,10 +14,7 @@ import Button from '../../atoms/button/Button';
import Input from '../../atoms/input/Input';
import Spinner from '../../atoms/spinner/Spinner';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
import { useStore } from '../../hooks/useStore';
@ -45,7 +43,7 @@ function SecretStorageAccess({ onComplete }) {
if (!mountStore.getItem()) return;
if (!isCorrect) {
setError(t(key ? "SecretStorageAccess.incorrect_security_key" : "SecretStorageAccess.incorrect_security_phrase"));
setError(t(key ? 'SecretStorageAccess.incorrect_security_key' : 'SecretStorageAccess.incorrect_security_phrase'));
setProcess(false);
return;
}
@ -57,7 +55,7 @@ function SecretStorageAccess({ onComplete }) {
});
} catch (e) {
if (!mountStore.getItem()) return;
setError(t(key ? "SecretStorageAccess.incorrect_security_key" : "SecretStorageAccess.incorrect_security_phrase"));
setError(t(key ? 'SecretStorageAccess.incorrect_security_key' : 'SecretStorageAccess.incorrect_security_phrase'));
setProcess(false);
}
};
@ -82,7 +80,7 @@ function SecretStorageAccess({ onComplete }) {
<form onSubmit={handleForm}>
<Input
name="password"
label={t(withPhrase ? "SecretStorageAccess.security_phrase" : "SecretStorageAccess.security_key")}
label={t(withPhrase ? 'SecretStorageAccess.security_phrase' : 'SecretStorageAccess.security_key')}
type="password"
onChange={handleChange}
required
@ -90,8 +88,8 @@ function SecretStorageAccess({ onComplete }) {
{error && <Text variant="b3">{error}</Text>}
{!process && (
<div className="secret-storage-access__btn">
<Button variant="primary" type="submit">{t("common.continue")}</Button>
{isPassphrase && <Button onClick={toggleWithPhrase}>{t( withPhrase ? "SecretStorageAccess.use_security_key" : "SecretStorageAccess.use_security_phrase")}</Button>}
<Button variant="primary" type="submit">{t('common.continue')}</Button>
{isPassphrase && <Button onClick={toggleWithPhrase}>{t(withPhrase ? 'SecretStorageAccess.use_security_key' : 'SecretStorageAccess.use_security_phrase')}</Button>}
</div>
)}
</form>

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import './Settings.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import settings from '../../../client/state/settings';
@ -40,8 +41,7 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import CinnySVG from '../../../../public/res/svg/cinny.svg';
import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function AppearanceSection() {
const [, updateState] = useState({});
@ -53,26 +53,26 @@ function AppearanceSection() {
<div className="settings-appearance__card">
<MenuHeader>Theme</MenuHeader>
<SettingTile
title={t("Organisms.Settings.theme.follow_system.title")}
title={t('Organisms.Settings.theme.follow_system.title')}
options={(
<Toggle
isActive={settings.useSystemTheme}
onToggle={() => { toggleSystemTheme(); updateState({}); }}
/>
)}
content={<Text variant="b3">{t("Organisms.Settings.theme.follow_system.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.theme.follow_system.description')}</Text>}
/>
{!settings.useSystemTheme && (
<SettingTile
title={t("Organisms.Settings.theme.title")}
title={t('Organisms.Settings.theme.title')}
content={(
<SegmentedControls
selected={settings.getThemeIndex()}
segments={[
{ text: t("Organisms.Settings.theme.theme_light") },
{ text: t("Organisms.Settings.theme.theme_silver") },
{ text: t("Organisms.Settings.theme.theme_dark") },
{ text: t("Organisms.Settings.theme.theme_butter") },
{ text: t('Organisms.Settings.theme.theme_light') },
{ text: t('Organisms.Settings.theme.theme_silver') },
{ text: t('Organisms.Settings.theme.theme_dark') },
{ text: t('Organisms.Settings.theme.theme_butter') },
]}
onSelect={(index) => settings.setTheme(index)}
/>
@ -83,34 +83,34 @@ function AppearanceSection() {
<div className="settings-appearance__card">
<MenuHeader>Room messages</MenuHeader>
<SettingTile
title={t("Organisms.Settings.markdown.title")}
title={t('Organisms.Settings.markdown.title')}
options={(
<Toggle
isActive={settings.isMarkdown}
onToggle={() => { toggleMarkdown(); updateState({}); }}
/>
)}
content={<Text variant="b3">{t("Organisms.Settings.markdown.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.markdown.description')}</Text>}
/>
<SettingTile
title={t("Organisms.Settings.hide_membership_events.title")}
title={t('Organisms.Settings.hide_membership_events.title')}
options={(
<Toggle
isActive={settings.hideMembershipEvents}
onToggle={() => { toggleMembershipEvents(); updateState({}); }}
/>
)}
content={<Text variant="b3">{t("Organisms.Settings.hide_membership_events.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.hide_membership_events.description')}</Text>}
/>
<SettingTile
title={t("Organisms.Settings.hide_nickname_avatar_events.title")}
title={t('Organisms.Settings.hide_nickname_avatar_events.title')}
options={(
<Toggle
isActive={settings.hideNickAvatarEvents}
onToggle={() => { toggleNickAvatarEvents(); updateState({}); }}
/>
)}
content={<Text variant="b3">{t("Organisms.Settings.hide_nickname_avatar_events.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.hide_nickname_avatar_events.description')}</Text>}
/>
</div>
</div>
@ -126,7 +126,7 @@ function NotificationsSection() {
const renderOptions = () => {
if (window.Notification === undefined) {
return <Text className="settings-notifications__not-supported">{t("errors.browser_not_supported")}</Text>;
return <Text className="settings-notifications__not-supported">{t('errors.browser_not_supported')}</Text>;
}
if (permission === 'granted') {
@ -154,54 +154,53 @@ function NotificationsSection() {
return (
<div className="settings-notifications">
<MenuHeader>{t("Organisms.Settings.notifications_and_sound.title")}</MenuHeader>
<MenuHeader>{t('Organisms.Settings.notifications_and_sound.title')}</MenuHeader>
<SettingTile
title={t("Organisms.Settings.notifications_and_sound.desktop.title")}
title={t('Organisms.Settings.notifications_and_sound.desktop.title')}
options={renderOptions()}
content={<Text variant="b3">{t("Organisms.Settings.notifications_and_sound.desktop.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.notifications_and_sound.desktop.description')}</Text>}
/>
<SettingTile
title={t("Organisms.Settings.notifications_and_sound.sound.title")}
title={t('Organisms.Settings.notifications_and_sound.sound.title')}
options={(
<Toggle
isActive={settings.isNotificationSounds}
onToggle={() => { toggleNotificationSounds(); updateState({}); }}
/>
)}
content={<Text variant="b3">{t("Organisms.Settings.notifications_and_sound.desktop.description")}</Text>}
content={<Text variant="b3">{t('Organisms.Settings.notifications_and_sound.desktop.description')}</Text>}
/>
</div>
);
}
function SecuritySection() {
const { t } = useTranslation();
return (
<div className="settings-security">
<div className="settings-security__card">
<MenuHeader>{t("Organisms.Settings.security.cross_signing.title")}</MenuHeader>
<MenuHeader>{t('Organisms.Settings.security.cross_signing.title')}</MenuHeader>
<CrossSigning />
<KeyBackup />
</div>
<DeviceManage />
<div className="settings-security__card">
<MenuHeader>{t("Organisms.Settings.security.export_import_encryption_keys.title")}</MenuHeader>
<MenuHeader>{t('Organisms.Settings.security.export_import_encryption_keys.title')}</MenuHeader>
<SettingTile
title={t("Organisms.Settings.security.export_encryption_keys.title")}
title={t('Organisms.Settings.security.export_encryption_keys.title')}
content={(
<>
<Text variant="b3">{t("Organisms.Settings.security.export_encryption_keys.description")}</Text>
<Text variant="b3">{t('Organisms.Settings.security.export_encryption_keys.description')}</Text>
<ExportE2ERoomKeys />
</>
)}
/>
<SettingTile
title={t("Organisms.Settings.security.import_encryption_keys.title")}
title={t('Organisms.Settings.security.import_encryption_keys.title')}
content={(
<>
<Text variant="b3">{t("Organisms.Settings.security.import_encryption_keys.description")}</Text>
<Text variant="b3">{t('Organisms.Settings.security.import_encryption_keys.description')}</Text>
<ImportE2ERoomKeys />
</>
)}
@ -212,31 +211,30 @@ function SecuritySection() {
}
function AboutSection() {
const { t } = useTranslation();
return (
<div className="settings-about">
<div className="settings-about__card">
<MenuHeader>{t("Organisms.Settings.about.application")}</MenuHeader>
<MenuHeader>{t('Organisms.Settings.about.application')}</MenuHeader>
<div className="settings-about__branding">
<img width="60" height="60" src={CinnySVG} alt="Cinny logo" />
<div>
<Text variant="h2" weight="medium">
{t("common.cinny")}
{t('common.cinny')}
<span className="text text-b3" style={{ margin: '0 var(--sp-extra-tight)' }}>{`v${cons.version}`}</span>
</Text>
<Text>{t("common.slogan")}</Text>
<Text>{t('common.slogan')}</Text>
<div className="settings-about__btns">
<Button onClick={() => window.open('https://github.com/ajbura/cinny')}>{t("common.source_code")}</Button>
<Button onClick={() => window.open('https://cinny.in/#sponsor')}>{t("common.sponsor")}</Button>
<Button onClick={() => window.open('https://github.com/ajbura/cinny')}>{t('common.source_code')}</Button>
<Button onClick={() => window.open('https://cinny.in/#sponsor')}>{t('common.sponsor')}</Button>
</div>
</div>
</div>
</div>
<div className="settings-about__card">
<MenuHeader>{t("Organisms.Settings.about.credits")}</MenuHeader>
<MenuHeader>{t('Organisms.Settings.about.credits')}</MenuHeader>
<div className="settings-about__credits">
<ul>
<li>
@ -314,7 +312,7 @@ function Settings() {
const handleTabChange = (tabItem) => setSelectedTab(tabItem);
const handleLogout = async () => {
if (await confirmDialog(t("Organisms.Settings.logout.dialog.title"), t("Organisms.Settings.logout.dialog.description"), t("Organisms.Settings.logout.dialog.confirm"), 'danger')) {
if (await confirmDialog(t('Organisms.Settings.logout.dialog.title'), t('Organisms.Settings.logout.dialog.description'), t('Organisms.Settings.logout.dialog.confirm'), 'danger')) {
logout();
}
};
@ -323,13 +321,13 @@ function Settings() {
<PopupWindow
isOpen={isOpen}
className="settings-window"
title={<Text variant="s1" weight="medium" primary>{t("Organisms.Settings.title")}</Text>}
title={<Text variant="s1" weight="medium" primary>{t('Organisms.Settings.title')}</Text>}
contentOptions={(
<>
<Button variant="danger" iconSrc={PowerIC} onClick={handleLogout}>
{t("Organisms.Settings.logout.title")}
{t('Organisms.Settings.logout.title')}
</Button>
<IconButton src={CrossIC} onClick={requestClose} tooltip={t("common.close")} />
<IconButton src={CrossIC} onClick={requestClose} tooltip={t('common.close')} />
</>
)}
onRequestClose={requestClose}

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import './ShortcutSpaces.scss';
import { useTranslation } from 'react-i18next';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
@ -22,9 +23,7 @@ import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useSpaceShortcut } from '../../hooks/useSpaceShortcut';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ShortcutSpacesContent() {
const mx = initMatrix.matrixClient;
@ -77,8 +76,6 @@ function ShortcutSpacesContent() {
const toggleSelected = () => toggleSelection(spaceId);
const deleteShortcut = () => deleteSpaceShortcut(spaceId);
const { t } = useTranslation();
return (
<RoomSelector
key={spaceId}
@ -115,18 +112,18 @@ function ShortcutSpacesContent() {
return (
<>
<Text className="shortcut-spaces__header" variant="b3" weight="bold">{t("Organisms.ShortcutSpaces.pinned_spaces")}</Text>
{spaceShortcut.length === 0 && <Text>{t("Organisms.ShortcutSpaces.no_pinned_spaces")}</Text>}
<Text className="shortcut-spaces__header" variant="b3" weight="bold">{t('Organisms.ShortcutSpaces.pinned_spaces')}</Text>
{spaceShortcut.length === 0 && <Text>{t('Organisms.ShortcutSpaces.no_pinned_spaces')}</Text>}
{spaceShortcut.map((spaceId) => renderSpace(spaceId, true))}
<Text className="shortcut-spaces__header" variant="b3" weight="bold">{t("Organisms.ShortcutSpaces.unpinned_spaces")}</Text>
{spaceWithoutShortcut.length === 0 && <Text>{t("Organisms.ShortcutSpaces.no_unpinned_spaces")}</Text>}
<Text className="shortcut-spaces__header" variant="b3" weight="bold">{t('Organisms.ShortcutSpaces.unpinned_spaces')}</Text>
{spaceWithoutShortcut.length === 0 && <Text>{t('Organisms.ShortcutSpaces.no_unpinned_spaces')}</Text>}
{spaceWithoutShortcut.map((spaceId) => renderSpace(spaceId, false))}
{selected.length !== 0 && (
<div className="shortcut-spaces__footer">
{process && <Spinner size="small" />}
<Text weight="medium">{process || t("Organisms.ShortcutSpaces.spaces_selected", {count: selected.length})}</Text>
<Text weight="medium">{process || t('Organisms.ShortcutSpaces.spaces_selected', { count: selected.length })}</Text>
{ !process && (
<Button onClick={handleAdd} variant="primary">{t("Organisms.ShortcutSpaces.pin_button")}</Button>
<Button onClick={handleAdd} variant="primary">{t('Organisms.ShortcutSpaces.pin_button')}</Button>
)}
</div>
)}
@ -160,10 +157,10 @@ function ShortcutSpaces() {
className="shortcut-spaces"
title={(
<Text variant="s1" weight="medium" primary>
{t("Organisms.ShortcutSpaces.header")}
{t('Organisms.ShortcutSpaces.header')}
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip= {t("common.close")}/>}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t('common.close')} />}
onRequestClose={requestClose}
>
{

View file

@ -3,6 +3,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './SpaceManage.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -32,9 +33,7 @@ import InfoIC from '../../../../public/res/ic/outlined/info.svg';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import { useStore } from '../../hooks/useStore';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function SpaceManageBreadcrumb({ path, onSelect }) {
return (
@ -120,7 +119,12 @@ function SpaceManageItem({
const roomNameJSX = (
<Text>
{twemojify(name)}
<Text variant="b3" span> {t("Organisms.SpaceManage.room_members", {count: roomInfo.num_joined_members})}</Text>
<Text variant="b3" span>
{' '}
{' '}
{t('Organisms.SpaceManage.room_members', { count: roomInfo.num_joined_members })}
</Text>
</Text>
);
@ -148,13 +152,13 @@ function SpaceManageItem({
>
{roomAvatarJSX}
{roomNameJSX}
{isSuggested && <Text variant="b2">{t("Organisms.SpaceManage.suggested")}</Text>}
{isSuggested && <Text variant="b2">{t('Organisms.SpaceManage.suggested')}</Text>}
</button>
{roomInfo.topic && expandBtnJsx}
{
isJoined
? <Button onClick={handleOpen}>{t("common.open")}</Button>
: <Button variant="primary" onClick={handleJoin} disabled={isJoining}>{t(isJoining ? "common.joining" : "common.join")}</Button>
? <Button onClick={handleOpen}>{t('common.open')}</Button>
: <Button variant="primary" onClick={handleJoin} disabled={isJoining}>{t(isJoining ? 'common.joining' : 'common.join')}</Button>
}
</div>
{isExpand && roomInfo.topic && <Text variant="b2">{twemojify(roomInfo.topic, undefined, true)}</Text>}
@ -162,7 +166,6 @@ function SpaceManageItem({
);
}
SpaceManageItem.propTypes = {
parentId: PropTypes.string.isRequired,
roomHierarchy: PropTypes.shape({}).isRequired,
@ -187,15 +190,15 @@ function SpaceManageFooter({ parentId, selected }) {
});
const handleRemove = () => {
setProcess(t("Organisms.SpaceManage.remove", {count: selected.length}));
setProcess(t('Organisms.SpaceManage.remove', { count: selected.length }));
selected.forEach((roomId) => {
mx.sendStateEvent(parentId, 'm.space.child', {}, roomId);
});
};
const handleToggleSuggested = (isMark) => {
if (isMark) setProcess(t("Organisms.SpaceManage.mark_suggested", {count: selected.length}));
else setProcess(t("Organisms.SpaceManage.mark_not_suggested", {count: selected.length}));
if (isMark) setProcess(t('Organisms.SpaceManage.mark_suggested', { count: selected.length }));
else setProcess(t('Organisms.SpaceManage.mark_not_suggested', { count: selected.length }));
selected.forEach((roomId) => {
const sEvent = room.currentState.getStateEvents('m.space.child', roomId);
if (!sEvent) return;
@ -210,10 +213,10 @@ function SpaceManageFooter({ parentId, selected }) {
return (
<div className="space-manage__footer">
{process && <Spinner size="small" />}
<Text weight="medium">{process || t("Organisms.SpaceManage.items_selected", {count: selected.length})}</Text>
<Text weight="medium">{process || t('Organisms.SpaceManage.items_selected', { count: selected.length })}</Text>
{ !process && (
<>
<Button onClick={handleRemove} variant="danger">{t("common.remove")}</Button>
<Button onClick={handleRemove} variant="danger">{t('common.remove')}</Button>
<Button
onClick={() => handleToggleSuggested(!allSuggested)}
variant={allSuggested ? 'surface' : 'primary'}
@ -292,7 +295,6 @@ function useChildUpdate(roomId, roomsHierarchy) {
}
function SpaceManageContent({ roomId, requestClose }) {
const { t } = useTranslation();
const mx = initMatrix.matrixClient;
@ -352,11 +354,11 @@ function SpaceManageContent({ roomId, requestClose }) {
{spacePath.length > 1 && (
<SpaceManageBreadcrumb path={spacePath} onSelect={addPathItem} />
)}
<Text variant="b3" weight="bold">{t("Organisms.SpaceManage.rooms_and_spaces")}</Text>
<Text variant="b3" weight="bold">{t('Organisms.SpaceManage.rooms_and_spaces')}</Text>
<div className="space-manage__content-items">
{!isLoading && currentHierarchy?.rooms?.length === 1 && (
<Text>
{t("Organisms.SpaceManage.private_rooms_message")}
{t('Organisms.SpaceManage.private_rooms_message')}
</Text>
)}
{currentHierarchy && (currentHierarchy.rooms?.map((roomInfo) => (
@ -375,15 +377,15 @@ function SpaceManageContent({ roomId, requestClose }) {
/>
)
)))}
{!currentHierarchy && <Text>{t("common.loading")}</Text>}
{!currentHierarchy && <Text>{t('common.loading')}</Text>}
</div>
{currentHierarchy?.canLoadMore && !isLoading && (
<Button onClick={loadRoomHierarchy}>{t("Organisms.SpaceManage.load_more")}</Button>
<Button onClick={loadRoomHierarchy}>{t('Organisms.SpaceManage.load_more')}</Button>
)}
{isLoading && (
<div className="space-manage__content-loading">
<Spinner size="small" />
<Text>{t("common.loading")}</Text>
<Text>{t('common.loading')}</Text>
</div>
)}
{selected.length > 0 && (
@ -428,7 +430,12 @@ function SpaceManage() {
title={(
<Text variant="s1" weight="medium" primary>
{roomId && twemojify(room.name)}
<span style={{ color: 'var(--tc-surface-low)' }}> {t("Organisms.SpaceManage.subtitle")}</span>
<span style={{ color: 'var(--tc-surface-low)' }}>
{' '}
{' '}
{t('Organisms.SpaceManage.subtitle')}
</span>
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip="Close" />}

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './SpaceSettings.scss';
import { useTranslation } from 'react-i18next';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
@ -39,9 +40,7 @@ import CategoryFilledIC from '../../../../public/res/ic/filled/category.svg';
import { confirmDialog } from '../../molecules/confirm-dialog/ConfirmDialog';
import { useForceUpdate } from '../../hooks/useForceUpdate';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
const tabText = {
GENERAL: 'General',
@ -74,7 +73,7 @@ function GeneralSettings({ roomId }) {
return (
<>
<div className="room-settings__card">
<MenuHeader>{t("common.options")}</MenuHeader>
<MenuHeader>{t('common.options')}</MenuHeader>
<MenuItem
onClick={() => {
if (isCategorized) unCategorizeSpace(roomId);
@ -83,7 +82,7 @@ function GeneralSettings({ roomId }) {
}}
iconSrc={isCategorized ? CategoryFilledIC : CategoryIC}
>
{isCategorized ? t("Organisms.SpaceSettings.uncategorize_subspaces") : t("Organisms.SpaceSettings.categorize_subspaces")}
{isCategorized ? t('Organisms.SpaceSettings.uncategorize_subspaces') : t('Organisms.SpaceSettings.categorize_subspaces')}
</MenuItem>
<MenuItem
onClick={() => {
@ -93,30 +92,30 @@ function GeneralSettings({ roomId }) {
}}
iconSrc={isPinned ? PinFilledIC : PinIC}
>
{isPinned ? t("Organisms.SpaceSettings.unpin_sidebar") : t("Organisms.SpaceSettings.pin_sidebar")}
{isPinned ? t('Organisms.SpaceSettings.unpin_sidebar') : t('Organisms.SpaceSettings.pin_sidebar')}
</MenuItem>
<MenuItem
variant="danger"
onClick={async () => {
const isConfirmed = await confirmDialog(
t("Organisms.SpaceSettings.leave.leave_dialog_title"),
t("Organisms.SpaceSettings.leave.leave_dialog_message", {space: roomName}),
t("Organisms.SpaceSettings.leave.leave_space"),
t('Organisms.SpaceSettings.leave.leave_dialog_title'),
t('Organisms.SpaceSettings.leave.leave_dialog_message', { space: roomName }),
t('Organisms.SpaceSettings.leave.leave_space'),
'danger',
);
if (isConfirmed) leave(roomId);
}}
iconSrc={LeaveArrowIC}
>
{t("Organisms.SpaceSettings.leave.leave_space")}
{t('Organisms.SpaceSettings.leave.leave_space')}
</MenuItem>
</div>
<div className="space-settings__card">
<MenuHeader>{t("Organisms.SpaceSettings.visibility.header")}</MenuHeader>
<MenuHeader>{t('Organisms.SpaceSettings.visibility.header')}</MenuHeader>
<RoomVisibility roomId={roomId} />
</div>
<div className="space-settings__card">
<MenuHeader>{t("Organisms.SpaceSettings.addresses.header")}</MenuHeader>
<MenuHeader>{t('Organisms.SpaceSettings.addresses.header')}</MenuHeader>
<RoomAliases roomId={roomId} />
</div>
</>
@ -169,10 +168,15 @@ function SpaceSettings() {
title={(
<Text variant="s1" weight="medium" primary>
{isOpen && twemojify(room.name)}
<span style={{ color: 'var(--tc-surface-low)' }}> {t("Organisms.SpaceSettings.subtitle")}</span>
<span style={{ color: 'var(--tc-surface-low)' }}>
{' '}
{' '}
{t('Organisms.SpaceSettings.subtitle')}
</span>
</Text>
)}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={requestClose} tooltip={t('common.close')} />}
onRequestClose={requestClose}
>
{isOpen && (

View file

@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import './ViewSource.scss';
import { useTranslation } from 'react-i18next';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
@ -12,8 +13,7 @@ import PopupWindow from '../../molecules/popup-window/PopupWindow';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function ViewSourceBlock({ title, json }) {
return (
@ -56,18 +56,18 @@ function ViewSource() {
const renderViewSource = () => (
<div className="view-source">
{event.isEncrypted() && <ViewSourceBlock title={t("Organisms.ViewSource.decrypted_source")} json={event.getEffectiveEvent()} />}
<ViewSourceBlock title={t("Organisms.ViewSource.original_source")} json={event.event} />
{event.isEncrypted() && <ViewSourceBlock title={t('Organisms.ViewSource.decrypted_source')} json={event.getEffectiveEvent()} />}
<ViewSourceBlock title={t('Organisms.ViewSource.original_source')} json={event.event} />
</div>
);
return (
<PopupWindow
isOpen={isOpen}
title={t("Organisms.ViewSource.title")}
title={t('Organisms.ViewSource.title')}
onAfterClose={handleAfterClose}
onRequestClose={() => setIsOpen(false)}
contentOptions={<IconButton src={CrossIC} onClick={() => setIsOpen(false)} tooltip={t("common.close")} />}
contentOptions={<IconButton src={CrossIC} onClick={() => setIsOpen(false)} tooltip={t('common.close')} />}
>
{event ? renderViewSource() : <div />}
</PopupWindow>

View file

@ -1,16 +1,15 @@
import React from 'react';
import './Welcome.scss';
import { useTranslation } from 'react-i18next';
import Text from '../../atoms/text/Text';
import CinnySvg from '../../../../public/res/svg/cinny.svg';
import '../../i18n.jsx'
import { useTranslation } from 'react-i18next';
import '../../i18n';
function Welcome() {
const { t, i18n } = useTranslation();
const { t } = useTranslation();
return (
<div className="app-welcome flex--center">

View file

@ -68,9 +68,7 @@ async function verifyEmail(baseUrl, email, client_secret, send_attempt, next_lin
return data;
}
async function completeRegisterStage(
baseUrl, username, password, auth,
) {
async function completeRegisterStage(baseUrl, username, password, auth) {
const tempClient = createTemporaryClient(baseUrl);
try {

View file

@ -177,7 +177,6 @@ function unpackMegolmKeyFile(data) {
return decodeBase64(fileStr.slice(dataStart, dataEnd));
}
/**
* ascii-armour a megolm key file
*
@ -196,7 +195,7 @@ function packMegolmKeyFile(data) {
let o = 0;
let i;
for (i = 1; i <= nLines; i += 1) {
lines[i] = encodeBase64(data.subarray(o, o+LINE_LENGTH));
lines[i] = encodeBase64(data.subarray(o, o + LINE_LENGTH));
o += LINE_LENGTH;
}
lines[i] = TRAILER_LINE;
@ -305,11 +304,11 @@ export async function encryptMegolmKeyFile(data, password, options) {
encodedData,
);
} catch (e) {
throw friendlyError('subtleCrypto.encrypt failed: ' + e, cryptoFailMsg());
throw friendlyError(`subtleCrypto.encrypt failed: ${e}`, cryptoFailMsg());
}
const cipherArray = new Uint8Array(ciphertext);
const bodyLength = (1+salt.length+iv.length+4+cipherArray.length+32);
const bodyLength = (1 + salt.length + iv.length + 4 + cipherArray.length + 32);
const resultBuffer = new Uint8Array(bodyLength);
let idx = 0;
resultBuffer[idx++] = 1; // version
@ -331,7 +330,7 @@ export async function encryptMegolmKeyFile(data, password, options) {
toSign,
);
} catch (e) {
throw friendlyError('subtleCrypto.sign failed: ' + e, cryptoFailMsg());
throw friendlyError(`subtleCrypto.sign failed: ${e}`, cryptoFailMsg());
}
const hmacArray = new Uint8Array(hmac);

View file

@ -39,7 +39,7 @@ export function getUsernameOfRoomMember(roomMember) {
return roomMember.name || roomMember.userId;
}
export function getUserDisplayName(room, userId){
export function getUserDisplayName(room, userId) {
if (room?.getMember(userId)) return getUsernameOfRoomMember(room.getMember(userId));
return getUsername(userId);
}