localize Add Space
This commit is contained in:
parent
456526315a
commit
45dc4fa8cf
13 changed files with 177 additions and 48 deletions
|
|
@ -554,5 +554,58 @@
|
||||||
"join_error_unknown": "Failed to join. Unknown Error.",
|
"join_error_unknown": "Failed to join. Unknown Error.",
|
||||||
"view_error": "View Error",
|
"view_error": "View Error",
|
||||||
"cancel": "Cancel"
|
"cancel": "Cancel"
|
||||||
|
},
|
||||||
|
|
||||||
|
"Create": {
|
||||||
|
"add_space": "Add Space",
|
||||||
|
"create_space": "Create Space",
|
||||||
|
"create_space_desc": "Build a space for your community.",
|
||||||
|
"join_with_address": "Join with Address",
|
||||||
|
"join_with_address_desc": "Join an existing community.",
|
||||||
|
"new_space": "New Space",
|
||||||
|
|
||||||
|
"access": "Access",
|
||||||
|
"name": "Name",
|
||||||
|
"topic_optional": "Topic (Optional)",
|
||||||
|
"options": "Options",
|
||||||
|
"advanced_options": "Advanced Options",
|
||||||
|
"knock_to_join": "Knock to Join",
|
||||||
|
"knock_to_join_desc": "Anyone can send a request to join this space.",
|
||||||
|
"allow_federation": "Allow Federation",
|
||||||
|
"allow_federation_desc": "Users from other servers can join.",
|
||||||
|
"create": "Create",
|
||||||
|
"rate_limited": "Server rate-limited your request for {{minutes}} minutes!",
|
||||||
|
|
||||||
|
"access_restricted": "Restricted",
|
||||||
|
"access_restricted_desc": "Only members of the parent space can join.",
|
||||||
|
"access_private": "Private",
|
||||||
|
"access_private_desc": "Only people with an invite can join.",
|
||||||
|
"access_public": "Public",
|
||||||
|
"access_public_desc": "Anyone with the address can join.",
|
||||||
|
|
||||||
|
"address_optional": "Address (Optional)",
|
||||||
|
"address_hint": "Pick a unique address to make it discoverable.",
|
||||||
|
"address_taken": "This address is already taken. Please choose a different one.",
|
||||||
|
|
||||||
|
"founders": "Founders",
|
||||||
|
"founders_desc": "Privileged users assigned during creation. They have elevated control and can only be changed during an upgrade.",
|
||||||
|
"enter": "Enter",
|
||||||
|
"no_suggestions": "No Suggestions",
|
||||||
|
"no_suggestions_desc": "Enter a user ID and press Enter.",
|
||||||
|
|
||||||
|
"version": "Version",
|
||||||
|
"versions": "Versions",
|
||||||
|
|
||||||
|
"chat_room": "Chat Room",
|
||||||
|
"chat_room_desc": "Messages, photos, and videos.",
|
||||||
|
"voice_room": "Voice Room",
|
||||||
|
"voice_room_desc": "Live audio and video conversations.",
|
||||||
|
|
||||||
|
"new_chat_room": "New Chat Room",
|
||||||
|
"new_voice_room": "New Voice Room",
|
||||||
|
|
||||||
|
"existing_space": "Existing Space",
|
||||||
|
"add_room": "Add Room",
|
||||||
|
"existing_room": "Existing Room"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -556,5 +556,58 @@
|
||||||
"join_error_unknown": "Не удалось присоединиться. Неизвестная ошибка.",
|
"join_error_unknown": "Не удалось присоединиться. Неизвестная ошибка.",
|
||||||
"view_error": "Подробности",
|
"view_error": "Подробности",
|
||||||
"cancel": "Отмена"
|
"cancel": "Отмена"
|
||||||
|
},
|
||||||
|
|
||||||
|
"Create": {
|
||||||
|
"add_space": "Добавить пространство",
|
||||||
|
"create_space": "Создать пространство",
|
||||||
|
"create_space_desc": "Создайте пространство для вашего сообщества.",
|
||||||
|
"join_with_address": "Присоединиться по адресу",
|
||||||
|
"join_with_address_desc": "Присоединиться к существующему сообществу.",
|
||||||
|
"new_space": "Новое пространство",
|
||||||
|
|
||||||
|
"access": "Доступ",
|
||||||
|
"name": "Название",
|
||||||
|
"topic_optional": "Тема (необязательно)",
|
||||||
|
"options": "Параметры",
|
||||||
|
"advanced_options": "Дополнительные параметры",
|
||||||
|
"knock_to_join": "Запрос на вступление",
|
||||||
|
"knock_to_join_desc": "Любой может отправить запрос на вступление в это пространство.",
|
||||||
|
"allow_federation": "Разрешить федерацию",
|
||||||
|
"allow_federation_desc": "Пользователи с других серверов смогут присоединиться.",
|
||||||
|
"create": "Создать",
|
||||||
|
"rate_limited": "Сервер ограничил ваш запрос на {{minutes}} мин.!",
|
||||||
|
|
||||||
|
"access_restricted": "Ограниченный",
|
||||||
|
"access_restricted_desc": "Могут присоединиться только участники родительского пространства.",
|
||||||
|
"access_private": "Приватный",
|
||||||
|
"access_private_desc": "Могут присоединиться только приглашённые.",
|
||||||
|
"access_public": "Публичный",
|
||||||
|
"access_public_desc": "Любой, у кого есть адрес, может присоединиться.",
|
||||||
|
|
||||||
|
"address_optional": "Адрес (необязательно)",
|
||||||
|
"address_hint": "Выберите уникальный адрес, чтобы пространство можно было найти.",
|
||||||
|
"address_taken": "Этот адрес уже занят. Выберите другой.",
|
||||||
|
|
||||||
|
"founders": "Основатели",
|
||||||
|
"founders_desc": "Привилегированные пользователи, назначенные при создании. Они имеют расширенные полномочия; изменить их можно только при обновлении пространства.",
|
||||||
|
"enter": "Добавить",
|
||||||
|
"no_suggestions": "Нет предложений",
|
||||||
|
"no_suggestions_desc": "Введите ID пользователя и нажмите Добавить.",
|
||||||
|
|
||||||
|
"version": "Версия",
|
||||||
|
"versions": "Версии",
|
||||||
|
|
||||||
|
"chat_room": "Чат-комната",
|
||||||
|
"chat_room_desc": "Сообщения, фото и видео.",
|
||||||
|
"voice_room": "Голосовая комната",
|
||||||
|
"voice_room_desc": "Голосовые и видеозвонки в реальном времени.",
|
||||||
|
|
||||||
|
"new_chat_room": "Новая чат-комната",
|
||||||
|
"new_voice_room": "Новая голосовая комната",
|
||||||
|
|
||||||
|
"existing_space": "Существующее пространство",
|
||||||
|
"add_room": "Добавить комнату",
|
||||||
|
"existing_room": "Существующая комната"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
import { isKeyHotkey } from 'is-hotkey';
|
import { isKeyHotkey } from 'is-hotkey';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import React, {
|
import React, {
|
||||||
ChangeEventHandler,
|
ChangeEventHandler,
|
||||||
KeyboardEventHandler,
|
KeyboardEventHandler,
|
||||||
|
|
@ -83,6 +84,7 @@ export function AdditionalCreatorInput({
|
||||||
onRemove,
|
onRemove,
|
||||||
disabled,
|
disabled,
|
||||||
}: AdditionalCreatorInputProps) {
|
}: AdditionalCreatorInputProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const [menuCords, setMenuCords] = useState<RectCords>();
|
const [menuCords, setMenuCords] = useState<RectCords>();
|
||||||
const directUsers = useDirectUsers();
|
const directUsers = useDirectUsers();
|
||||||
|
|
@ -150,8 +152,8 @@ export function AdditionalCreatorInput({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title="Founders"
|
title={t('Create.founders')}
|
||||||
description="Special privileged users can be assigned during creation. These users have elevated control and can only be modified during a upgrade."
|
description={t('Create.founders_desc')}
|
||||||
>
|
>
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Box gap="200" wrap="Wrap">
|
<Box gap="200" wrap="Wrap">
|
||||||
|
|
@ -213,7 +215,7 @@ export function AdditionalCreatorInput({
|
||||||
onClick={handleEnterClick}
|
onClick={handleEnterClick}
|
||||||
disabled={!validUserId}
|
disabled={!validUserId}
|
||||||
>
|
>
|
||||||
<Text size="B400">Enter</Text>
|
<Text size="B400">{t('Create.enter')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
<Line size="300" />
|
<Line size="300" />
|
||||||
|
|
@ -263,10 +265,10 @@ export function AdditionalCreatorInput({
|
||||||
gap="100"
|
gap="100"
|
||||||
>
|
>
|
||||||
<Text size="H6" align="Center">
|
<Text size="H6" align="Center">
|
||||||
No Suggestions
|
{t('Create.no_suggestions')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="T200" align="Center">
|
<Text size="T200" align="Center">
|
||||||
Please provide the user ID and hit Enter.
|
{t('Create.no_suggestions_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text, Icon, Icons, config, IconSrc } from 'folds';
|
import { Box, Text, Icon, Icons, config, IconSrc } from 'folds';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SequenceCard } from '../sequence-card';
|
import { SequenceCard } from '../sequence-card';
|
||||||
import { SettingTile } from '../setting-tile';
|
import { SettingTile } from '../setting-tile';
|
||||||
import { CreateRoomAccess } from './types';
|
import { CreateRoomAccess } from './types';
|
||||||
|
|
@ -18,6 +19,7 @@ export function CreateRoomAccessSelector({
|
||||||
disabled,
|
disabled,
|
||||||
getIcon,
|
getIcon,
|
||||||
}: CreateRoomAccessSelectorProps) {
|
}: CreateRoomAccessSelectorProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
{canRestrict && (
|
{canRestrict && (
|
||||||
|
|
@ -36,9 +38,9 @@ export function CreateRoomAccessSelector({
|
||||||
before={<Icon size="400" src={getIcon(CreateRoomAccess.Restricted)} />}
|
before={<Icon size="400" src={getIcon(CreateRoomAccess.Restricted)} />}
|
||||||
after={value === CreateRoomAccess.Restricted && <Icon src={Icons.Check} />}
|
after={value === CreateRoomAccess.Restricted && <Icon src={Icons.Check} />}
|
||||||
>
|
>
|
||||||
<Text size="H6">Restricted</Text>
|
<Text size="H6">{t('Create.access_restricted')}</Text>
|
||||||
<Text size="T300" priority="300">
|
<Text size="T300" priority="300">
|
||||||
Only member of parent space can join.
|
{t('Create.access_restricted_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
@ -58,9 +60,9 @@ export function CreateRoomAccessSelector({
|
||||||
before={<Icon size="400" src={getIcon(CreateRoomAccess.Private)} />}
|
before={<Icon size="400" src={getIcon(CreateRoomAccess.Private)} />}
|
||||||
after={value === CreateRoomAccess.Private && <Icon src={Icons.Check} />}
|
after={value === CreateRoomAccess.Private && <Icon src={Icons.Check} />}
|
||||||
>
|
>
|
||||||
<Text size="H6">Private</Text>
|
<Text size="H6">{t('Create.access_private')}</Text>
|
||||||
<Text size="T300" priority="300">
|
<Text size="T300" priority="300">
|
||||||
Only people with invite can join.
|
{t('Create.access_private_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
@ -79,9 +81,9 @@ export function CreateRoomAccessSelector({
|
||||||
before={<Icon size="400" src={getIcon(CreateRoomAccess.Public)} />}
|
before={<Icon size="400" src={getIcon(CreateRoomAccess.Public)} />}
|
||||||
after={value === CreateRoomAccess.Public && <Icon src={Icons.Check} />}
|
after={value === CreateRoomAccess.Public && <Icon src={Icons.Check} />}
|
||||||
>
|
>
|
||||||
<Text size="H6">Public</Text>
|
<Text size="H6">{t('Create.access_public')}</Text>
|
||||||
<Text size="T300" priority="300">
|
<Text size="T300" priority="300">
|
||||||
Anyone with the address can join.
|
{t('Create.access_public_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import React, {
|
||||||
import { MatrixError } from 'matrix-js-sdk';
|
import { MatrixError } from 'matrix-js-sdk';
|
||||||
import { Box, color, Icon, Icons, Input, Spinner, Text, toRem } from 'folds';
|
import { Box, color, Icon, Icons, Input, Spinner, Text, toRem } from 'folds';
|
||||||
import { isKeyHotkey } from 'is-hotkey';
|
import { isKeyHotkey } from 'is-hotkey';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getMxIdServer } from '../../utils/matrix';
|
import { getMxIdServer } from '../../utils/matrix';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { replaceSpaceWithDash } from '../../utils/common';
|
import { replaceSpaceWithDash } from '../../utils/common';
|
||||||
|
|
@ -16,6 +17,7 @@ import { AsyncState, AsyncStatus, useAsync } from '../../hooks/useAsyncCallback'
|
||||||
import { useDebounce } from '../../hooks/useDebounce';
|
import { useDebounce } from '../../hooks/useDebounce';
|
||||||
|
|
||||||
export function CreateRoomAliasInput({ disabled }: { disabled?: boolean }) {
|
export function CreateRoomAliasInput({ disabled }: { disabled?: boolean }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const aliasInputRef = useRef<HTMLInputElement>(null);
|
const aliasInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [aliasAvail, setAliasAvail] = useState<AsyncState<boolean, Error>>({
|
const [aliasAvail, setAliasAvail] = useState<AsyncState<boolean, Error>>({
|
||||||
|
|
@ -78,9 +80,9 @@ export function CreateRoomAliasInput({ disabled }: { disabled?: boolean }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Text size="L400">Address (Optional)</Text>
|
<Text size="L400">{t('Create.address_optional')}</Text>
|
||||||
<Text size="T200" priority="300">
|
<Text size="T200" priority="300">
|
||||||
Pick an unique address to make it discoverable.
|
{t('Create.address_hint')}
|
||||||
</Text>
|
</Text>
|
||||||
<Input
|
<Input
|
||||||
ref={aliasInputRef}
|
ref={aliasInputRef}
|
||||||
|
|
@ -109,7 +111,7 @@ export function CreateRoomAliasInput({ disabled }: { disabled?: boolean }) {
|
||||||
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
|
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
|
||||||
<Icon src={Icons.Warning} filled size="50" />
|
<Icon src={Icons.Warning} filled size="50" />
|
||||||
<Text size="T200">
|
<Text size="T200">
|
||||||
<b>This address is already taken. Please select a different one.</b>
|
<b>{t('Create.address_taken')}</b>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Text, Icon, Icons, config, IconSrc } from 'folds';
|
import { Box, Text, Icon, Icons, config, IconSrc } from 'folds';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SequenceCard } from '../sequence-card';
|
import { SequenceCard } from '../sequence-card';
|
||||||
import { SettingTile } from '../setting-tile';
|
import { SettingTile } from '../setting-tile';
|
||||||
import { CreateRoomType } from './types';
|
import { CreateRoomType } from './types';
|
||||||
|
|
@ -17,6 +18,7 @@ export function CreateRoomTypeSelector({
|
||||||
disabled,
|
disabled,
|
||||||
getIcon,
|
getIcon,
|
||||||
}: CreateRoomTypeSelectorProps) {
|
}: CreateRoomTypeSelectorProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<SequenceCard
|
<SequenceCard
|
||||||
|
|
@ -36,10 +38,10 @@ export function CreateRoomTypeSelector({
|
||||||
>
|
>
|
||||||
<Box gap="200" alignItems="Baseline">
|
<Box gap="200" alignItems="Baseline">
|
||||||
<Text size="H6" style={{ flexShrink: 0 }}>
|
<Text size="H6" style={{ flexShrink: 0 }}>
|
||||||
Chat Room
|
{t('Create.chat_room')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="T300" priority="300" truncate>
|
<Text size="T300" priority="300" truncate>
|
||||||
- Messages, photos, and videos.
|
- {t('Create.chat_room_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
|
|
@ -61,10 +63,10 @@ export function CreateRoomTypeSelector({
|
||||||
>
|
>
|
||||||
<Box gap="200" alignItems="Baseline">
|
<Box gap="200" alignItems="Baseline">
|
||||||
<Text size="H6" style={{ flexShrink: 0 }}>
|
<Text size="H6" style={{ flexShrink: 0 }}>
|
||||||
Voice Room
|
{t('Create.voice_room')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="T300" priority="300" truncate>
|
<Text size="T300" priority="300" truncate>
|
||||||
- Live audio and video conversations.
|
- {t('Create.voice_room_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
<BetaNoticeBadge />
|
<BetaNoticeBadge />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { MouseEventHandler, useState } from 'react';
|
import React, { MouseEventHandler, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
|
@ -28,6 +29,7 @@ export function RoomVersionSelector({
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [menuCords, setMenuCords] = useState<RectCords>();
|
const [menuCords, setMenuCords] = useState<RectCords>();
|
||||||
|
|
||||||
const handleMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
const handleMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||||
|
|
@ -47,7 +49,7 @@ export function RoomVersionSelector({
|
||||||
gap="500"
|
gap="500"
|
||||||
>
|
>
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title="Version"
|
title={t('Create.version')}
|
||||||
after={
|
after={
|
||||||
<PopOut
|
<PopOut
|
||||||
anchor={menuCords}
|
anchor={menuCords}
|
||||||
|
|
@ -73,7 +75,7 @@ export function RoomVersionSelector({
|
||||||
gap="200"
|
gap="200"
|
||||||
style={{ padding: config.space.S200, maxWidth: toRem(300) }}
|
style={{ padding: config.space.S200, maxWidth: toRem(300) }}
|
||||||
>
|
>
|
||||||
<Text size="L400">Versions</Text>
|
<Text size="L400">{t('Create.versions')}</Text>
|
||||||
<Box wrap="Wrap" gap="100">
|
<Box wrap="Wrap" gap="100">
|
||||||
{versions.map((version) => (
|
{versions.map((version) => (
|
||||||
<Chip
|
<Chip
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
Text,
|
Text,
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAllJoinedRoomsSet, useGetRoom } from '../../hooks/useGetRoom';
|
import { useAllJoinedRoomsSet, useGetRoom } from '../../hooks/useGetRoom';
|
||||||
import { SpaceProvider } from '../../hooks/useSpace';
|
import { SpaceProvider } from '../../hooks/useSpace';
|
||||||
import { CreateRoomForm } from './CreateRoom';
|
import { CreateRoomForm } from './CreateRoom';
|
||||||
|
|
@ -29,6 +30,7 @@ type CreateRoomModalProps = {
|
||||||
state: CreateRoomModalState;
|
state: CreateRoomModalState;
|
||||||
};
|
};
|
||||||
function CreateRoomModal({ state }: CreateRoomModalProps) {
|
function CreateRoomModal({ state }: CreateRoomModalProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { spaceId, type } = state;
|
const { spaceId, type } = state;
|
||||||
const closeDialog = useCloseCreateRoomModal();
|
const closeDialog = useCloseCreateRoomModal();
|
||||||
|
|
||||||
|
|
@ -59,7 +61,7 @@ function CreateRoomModal({ state }: CreateRoomModalProps) {
|
||||||
>
|
>
|
||||||
<Box grow="Yes">
|
<Box grow="Yes">
|
||||||
<Text size="H4">
|
<Text size="H4">
|
||||||
{type === CreateRoomType.VoiceRoom ? 'New Voice Room' : 'New Chat Room'}
|
{type === CreateRoomType.VoiceRoom ? t('Create.new_voice_room') : t('Create.new_chat_room')}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No">
|
<Box shrink="No">
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
Text,
|
Text,
|
||||||
TextArea,
|
TextArea,
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SettingTile } from '../../components/setting-tile';
|
import { SettingTile } from '../../components/setting-tile';
|
||||||
import { SequenceCard } from '../../components/sequence-card';
|
import { SequenceCard } from '../../components/sequence-card';
|
||||||
import {
|
import {
|
||||||
|
|
@ -52,6 +53,7 @@ type CreateSpaceFormProps = {
|
||||||
onCreate?: (roomId: string) => void;
|
onCreate?: (roomId: string) => void;
|
||||||
};
|
};
|
||||||
export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceFormProps) {
|
export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceFormProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const alive = useAlive();
|
const alive = useAlive();
|
||||||
|
|
||||||
|
|
@ -138,7 +140,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
return (
|
return (
|
||||||
<Box as="form" onSubmit={handleSubmit} grow="Yes" direction="Column" gap="500">
|
<Box as="form" onSubmit={handleSubmit} grow="Yes" direction="Column" gap="500">
|
||||||
<Box direction="Column" gap="100">
|
<Box direction="Column" gap="100">
|
||||||
<Text size="L400">Access</Text>
|
<Text size="L400">{t('Create.access')}</Text>
|
||||||
<CreateRoomAccessSelector
|
<CreateRoomAccessSelector
|
||||||
value={access}
|
value={access}
|
||||||
onSelect={setAccess}
|
onSelect={setAccess}
|
||||||
|
|
@ -148,7 +150,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Text size="L400">Name</Text>
|
<Text size="L400">{t('Create.name')}</Text>
|
||||||
<Input
|
<Input
|
||||||
required
|
required
|
||||||
before={<Icon size="100" src={getCreateSpaceAccessToIcon(access)} />}
|
before={<Icon size="100" src={getCreateSpaceAccessToIcon(access)} />}
|
||||||
|
|
@ -162,7 +164,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Text size="L400">Topic (Optional)</Text>
|
<Text size="L400">{t('Create.topic_optional')}</Text>
|
||||||
<TextArea
|
<TextArea
|
||||||
name="topicTextAria"
|
name="topicTextAria"
|
||||||
size="500"
|
size="500"
|
||||||
|
|
@ -176,7 +178,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
|
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<Box shrink="No" direction="Column" gap="100">
|
||||||
<Box gap="200" alignItems="End">
|
<Box gap="200" alignItems="End">
|
||||||
<Text size="L400">Options</Text>
|
<Text size="L400">{t('Create.options')}</Text>
|
||||||
<Box grow="Yes" justifyContent="End">
|
<Box grow="Yes" justifyContent="End">
|
||||||
<Chip
|
<Chip
|
||||||
radii="Pill"
|
radii="Pill"
|
||||||
|
|
@ -184,7 +186,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
onClick={() => setAdvance(!advance)}
|
onClick={() => setAdvance(!advance)}
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<Text size="T200">Advanced Options</Text>
|
<Text size="T200">{t('Create.advanced_options')}</Text>
|
||||||
</Chip>
|
</Chip>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -210,8 +212,8 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
gap="500"
|
gap="500"
|
||||||
>
|
>
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title="Knock to Join"
|
title={t('Create.knock_to_join')}
|
||||||
description="Anyone can send request to join this space."
|
description={t('Create.knock_to_join_desc')}
|
||||||
after={
|
after={
|
||||||
<Switch variant="Primary" value={knock} onChange={setKnock} disabled={disabled} />
|
<Switch variant="Primary" value={knock} onChange={setKnock} disabled={disabled} />
|
||||||
}
|
}
|
||||||
|
|
@ -226,8 +228,8 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
gap="500"
|
gap="500"
|
||||||
>
|
>
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title="Allow Federation"
|
title={t('Create.allow_federation')}
|
||||||
description="Users from other servers can join."
|
description={t('Create.allow_federation_desc')}
|
||||||
after={
|
after={
|
||||||
<Switch
|
<Switch
|
||||||
variant="Primary"
|
variant="Primary"
|
||||||
|
|
@ -254,9 +256,9 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
<Text size="T300" style={{ color: color.Critical.Main }}>
|
<Text size="T300" style={{ color: color.Critical.Main }}>
|
||||||
<b>
|
<b>
|
||||||
{error instanceof MatrixError && error.name === ErrorCode.M_LIMIT_EXCEEDED
|
{error instanceof MatrixError && error.name === ErrorCode.M_LIMIT_EXCEEDED
|
||||||
? `Server rate-limited your request for ${millisecondsToMinutes(
|
? t('Create.rate_limited', { minutes: millisecondsToMinutes(
|
||||||
(error.data.retry_after_ms as number | undefined) ?? 0
|
(error.data.retry_after_ms as number | undefined) ?? 0
|
||||||
)} minutes!`
|
) })
|
||||||
: error.message}
|
: error.message}
|
||||||
</b>
|
</b>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
@ -271,7 +273,7 @@ export function CreateSpaceForm({ defaultAccess, space, onCreate }: CreateSpaceF
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
before={loading && <Spinner variant="Primary" fill="Solid" size="200" />}
|
before={loading && <Spinner variant="Primary" fill="Solid" size="200" />}
|
||||||
>
|
>
|
||||||
<Text size="B500">Create</Text>
|
<Text size="B500">{t('Create.create')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
Text,
|
Text,
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAllJoinedRoomsSet, useGetRoom } from '../../hooks/useGetRoom';
|
import { useAllJoinedRoomsSet, useGetRoom } from '../../hooks/useGetRoom';
|
||||||
import { SpaceProvider } from '../../hooks/useSpace';
|
import { SpaceProvider } from '../../hooks/useSpace';
|
||||||
import { CreateSpaceForm } from './CreateSpace';
|
import { CreateSpaceForm } from './CreateSpace';
|
||||||
|
|
@ -28,6 +29,7 @@ type CreateSpaceModalProps = {
|
||||||
state: CreateSpaceModalState;
|
state: CreateSpaceModalState;
|
||||||
};
|
};
|
||||||
function CreateSpaceModal({ state }: CreateSpaceModalProps) {
|
function CreateSpaceModal({ state }: CreateSpaceModalProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { spaceId } = state;
|
const { spaceId } = state;
|
||||||
const closeDialog = useCloseCreateSpaceModal();
|
const closeDialog = useCloseCreateSpaceModal();
|
||||||
|
|
||||||
|
|
@ -58,7 +60,7 @@ function CreateSpaceModal({ state }: CreateSpaceModalProps) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box grow="Yes">
|
<Box grow="Yes">
|
||||||
<Text size="H4">New Space</Text>
|
<Text size="H4">{t('Create.new_space')}</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No">
|
<Box shrink="No">
|
||||||
<IconButton size="300" radii="300" onClick={closeDialog}>
|
<IconButton size="300" radii="300" onClick={closeDialog}>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
config,
|
config,
|
||||||
} from 'folds';
|
} from 'folds';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { MatrixError, Room } from 'matrix-js-sdk';
|
import { MatrixError, Room } from 'matrix-js-sdk';
|
||||||
import { IHierarchyRoom } from 'matrix-js-sdk/lib/@types/spaces';
|
import { IHierarchyRoom } from 'matrix-js-sdk/lib/@types/spaces';
|
||||||
|
|
@ -243,6 +244,7 @@ function RootSpaceProfile({ closed, categoryId, handleClose }: RootSpaceProfileP
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddRoomButton({ item }: { item: HierarchyItem }) {
|
function AddRoomButton({ item }: { item: HierarchyItem }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [cords, setCords] = useState<RectCords>();
|
const [cords, setCords] = useState<RectCords>();
|
||||||
const openCreateRoomModal = useOpenCreateRoomModal();
|
const openCreateRoomModal = useOpenCreateRoomModal();
|
||||||
const [addExisting, setAddExisting] = useState(false);
|
const [addExisting, setAddExisting] = useState(false);
|
||||||
|
|
@ -285,7 +287,7 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
|
||||||
fill="None"
|
fill="None"
|
||||||
onClick={() => handleCreateRoom(CreateRoomType.TextRoom)}
|
onClick={() => handleCreateRoom(CreateRoomType.TextRoom)}
|
||||||
>
|
>
|
||||||
<Text size="T300">Chat Room</Text>
|
<Text size="T300">{t('Create.chat_room')}</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
size="300"
|
size="300"
|
||||||
|
|
@ -295,10 +297,10 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
|
||||||
onClick={() => handleCreateRoom(CreateRoomType.VoiceRoom)}
|
onClick={() => handleCreateRoom(CreateRoomType.VoiceRoom)}
|
||||||
after={<BetaNoticeBadge />}
|
after={<BetaNoticeBadge />}
|
||||||
>
|
>
|
||||||
<Text size="T300">Voice Room</Text>
|
<Text size="T300">{t('Create.voice_room')}</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem size="300" radii="300" fill="None" onClick={handleAddExisting}>
|
<MenuItem size="300" radii="300" fill="None" onClick={handleAddExisting}>
|
||||||
<Text size="T300">Existing Room</Text>
|
<Text size="T300">{t('Create.existing_room')}</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</FocusTrap>
|
</FocusTrap>
|
||||||
|
|
@ -311,7 +313,7 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
|
||||||
onClick={handleAddRoom}
|
onClick={handleAddRoom}
|
||||||
aria-pressed={!!cords}
|
aria-pressed={!!cords}
|
||||||
>
|
>
|
||||||
<Text size="B300">Add Room</Text>
|
<Text size="B300">{t('Create.add_room')}</Text>
|
||||||
</Chip>
|
</Chip>
|
||||||
{addExisting && (
|
{addExisting && (
|
||||||
<AddExistingModal parentId={item.roomId} requestClose={() => setAddExisting(false)} />
|
<AddExistingModal parentId={item.roomId} requestClose={() => setAddExisting(false)} />
|
||||||
|
|
@ -321,6 +323,7 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddSpaceButton({ item }: { item: HierarchyItem }) {
|
function AddSpaceButton({ item }: { item: HierarchyItem }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [cords, setCords] = useState<RectCords>();
|
const [cords, setCords] = useState<RectCords>();
|
||||||
const openCreateSpaceModal = useOpenCreateSpaceModal();
|
const openCreateSpaceModal = useOpenCreateSpaceModal();
|
||||||
const [addExisting, setAddExisting] = useState(false);
|
const [addExisting, setAddExisting] = useState(false);
|
||||||
|
|
@ -362,10 +365,10 @@ function AddSpaceButton({ item }: { item: HierarchyItem }) {
|
||||||
fill="None"
|
fill="None"
|
||||||
onClick={handleCreateSpace}
|
onClick={handleCreateSpace}
|
||||||
>
|
>
|
||||||
<Text size="T300">New Space</Text>
|
<Text size="T300">{t('Create.new_space')}</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem size="300" radii="300" fill="None" onClick={handleAddExisting}>
|
<MenuItem size="300" radii="300" fill="None" onClick={handleAddExisting}>
|
||||||
<Text size="T300">Existing Space</Text>
|
<Text size="T300">{t('Create.existing_space')}</Text>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</FocusTrap>
|
</FocusTrap>
|
||||||
|
|
@ -378,7 +381,7 @@ function AddSpaceButton({ item }: { item: HierarchyItem }) {
|
||||||
onClick={handleAddSpace}
|
onClick={handleAddSpace}
|
||||||
aria-pressed={!!cords}
|
aria-pressed={!!cords}
|
||||||
>
|
>
|
||||||
<Text size="B300">Add Space</Text>
|
<Text size="B300">{t('Create.add_space')}</Text>
|
||||||
</Chip>
|
</Chip>
|
||||||
{addExisting && (
|
{addExisting && (
|
||||||
<AddExistingModal space parentId={item.roomId} requestClose={() => setAddExisting(false)} />
|
<AddExistingModal space parentId={item.roomId} requestClose={() => setAddExisting(false)} />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Icon, Icons, Scroll } from 'folds';
|
import { Box, Icon, Icons, Scroll } from 'folds';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
Page,
|
Page,
|
||||||
PageContent,
|
PageContent,
|
||||||
|
|
@ -11,6 +12,7 @@ import { CreateSpaceForm } from '../../../features/create-space';
|
||||||
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
|
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
|
||||||
|
|
||||||
export function Create() {
|
export function Create() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { navigateSpace } = useRoomNavigate();
|
const { navigateSpace } = useRoomNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -23,8 +25,8 @@ export function Create() {
|
||||||
<Box direction="Column" gap="700">
|
<Box direction="Column" gap="700">
|
||||||
<PageHero
|
<PageHero
|
||||||
icon={<Icon size="600" src={Icons.Space} />}
|
icon={<Icon size="600" src={Icons.Space} />}
|
||||||
title="Create Space"
|
title={t('Create.create_space')}
|
||||||
subTitle="Build a space for your community."
|
subTitle={t('Create.create_space_desc')}
|
||||||
/>
|
/>
|
||||||
<CreateSpaceForm onCreate={navigateSpace} />
|
<CreateSpaceForm onCreate={navigateSpace} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React, { MouseEventHandler, useState } from 'react';
|
||||||
import { Box, config, Icon, Icons, Menu, PopOut, RectCords, Text } from 'folds';
|
import { Box, config, Icon, Icons, Menu, PopOut, RectCords, Text } from 'folds';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SidebarAvatar, SidebarItem, SidebarItemTooltip } from '../../../components/sidebar';
|
import { SidebarAvatar, SidebarItem, SidebarItemTooltip } from '../../../components/sidebar';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
import { SequenceCard } from '../../../components/sequence-card';
|
import { SequenceCard } from '../../../components/sequence-card';
|
||||||
|
|
@ -18,6 +19,7 @@ import { JoinAddressPrompt } from '../../../components/join-address-prompt';
|
||||||
import { _RoomSearchParams } from '../../paths';
|
import { _RoomSearchParams } from '../../paths';
|
||||||
|
|
||||||
export function CreateTab() {
|
export function CreateTab() {
|
||||||
|
const { t } = useTranslation();
|
||||||
const createSelected = useCreateSelected();
|
const createSelected = useCreateSelected();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
@ -40,7 +42,7 @@ export function CreateTab() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarItem active={createSelected}>
|
<SidebarItem active={createSelected}>
|
||||||
<SidebarItemTooltip tooltip="Add Space">
|
<SidebarItemTooltip tooltip={t('Create.add_space')}>
|
||||||
{(triggerRef) => (
|
{(triggerRef) => (
|
||||||
<PopOut
|
<PopOut
|
||||||
anchor={menuCords}
|
anchor={menuCords}
|
||||||
|
|
@ -73,9 +75,9 @@ export function CreateTab() {
|
||||||
onClick={handleCreateSpace}
|
onClick={handleCreateSpace}
|
||||||
>
|
>
|
||||||
<SettingTile before={<Icon size="400" src={Icons.Space} />}>
|
<SettingTile before={<Icon size="400" src={Icons.Space} />}>
|
||||||
<Text size="H6">Create Space</Text>
|
<Text size="H6">{t('Create.create_space')}</Text>
|
||||||
<Text size="T300" priority="300">
|
<Text size="T300" priority="300">
|
||||||
Build a space for your community.
|
{t('Create.create_space_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
@ -90,9 +92,9 @@ export function CreateTab() {
|
||||||
onClick={handleJoinWithAddress}
|
onClick={handleJoinWithAddress}
|
||||||
>
|
>
|
||||||
<SettingTile before={<Icon size="400" src={Icons.Link} />}>
|
<SettingTile before={<Icon size="400" src={Icons.Link} />}>
|
||||||
<Text size="H6">Join with Address</Text>
|
<Text size="H6">{t('Create.join_with_address')}</Text>
|
||||||
<Text size="T300" priority="300">
|
<Text size="T300" priority="300">
|
||||||
Become a part of existing community.
|
{t('Create.join_with_address_desc')}
|
||||||
</Text>
|
</Text>
|
||||||
</SettingTile>
|
</SettingTile>
|
||||||
</SequenceCard>
|
</SequenceCard>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue